More from Miguel Carranza
I’m back in Spain for my brother’s wedding. I rarely visit during the summer. The heat in my hometown is brutal, around 40 degrees Celsius (over 100 Fahrenheit for my imperial friends). Most people escape to the coast, just like my family did when I was a kid. I haven’t been here in years. As I drive along the coast, I find myself reflecting on a tweet about money and happiness, a vivid memory pulls me back in time. It’s August 22nd, 2007. The iPhone, the first real smartphone, has just been announced. It’s so cool, but of course I cannot afford it. It’s not even going to be released in Spain. I’ve just gotten my driver’s license, and I’m about to dive into my third year of Computer Science. I set up my clunky TomTom navigator knockoff, and hit the road. I’m on my way to meet Marina for our first real date. She’s cool, pretty, and kind. She likes the same music as I do, and even has distant relatives in California, the place we jokingly plan to visit someday (if I ever get enough cash). I’m listening to a pirated Blink-182’s self-titled CD. Pop-punk is pretty niche in the south of Spain, and it’s dying. Blink-182 has split up, and I missed my window to see my favorite band live. The Atlantic Ocean is as flat as a lake. This corner of Huelva’s coast is sheltered from any real waves, a stark contrast to the world-class surf breaks I drool over in magazines. And suddenly, reality hits: my childhood dreams of building a tech company in Silicon Valley, while vacationing in Southern California feel impossibly far. Even getting through my degree feels like a pipe dream. School isn’t fun anymore. It’s grueling, especially the parts I thought I’d enjoy, like algorithms and Data Structures. I might never become a Software Engineer. I feel stuck, trapped by my lack of direction. I am seriously considering quitting. But no degree means no job in the US, and good tech gigs are rare here in Spain. The only cool company is Tuenti, a new startup that is cloning Facebook. I’m nowhere near smart enough to land a job there though. Flash forward to today, 17 years later. It’s almost laughable to think about how hopeless things once seemed. Even now, it doesn’t feel like I’ve “made it.” The path and the results look nothing like what teenage me envisioned, but somehow, I’m realizing I’ve kind of checked off every box. I married Marina, and we live in Southern California with our two beautiful identical kids. We’ve become American citizens, and I’ve lived in the Golden State for nearly a third of my life. I’ve worked as a Software Engineer at a Silicon Valley startup, learned from the best, and found the best co-founder I could ask for. We launched our own company. Smartphones? They’re in everyone’s pockets now. Our product is in a third of all new apps shipped in the US. We’ve helped developers reach millionaire status, and we’ve made more money than I ever thought possible. But I’ve learned that a lot of money is a relative term. Somehow, I managed to hire insanely talented engineers—a bunch of them, ironically, from Tuenti. Blink-182 is back together, and I’ve been fortunate enough to see them live five times. I’ve even bumped into Tom Delonge after surfing world-class waves a few times. I’m literally just realizing how surreal all of this is. I tend to get caught up in the chaos of what’s next—the next big fire, the next goal—but sometimes you’ve got to stop, be present, and reflect on how far you’ve come. It wasn’t easy. It wasn’t without loss, sacrifice, and a fair share of doubts. Am I truly happy? Maybe not in a perfect, all-the-time kind of way. There are external things humans cannot control. But when I look at my life, I realize there’s no real reason not to be. The journey has been was worth it so far: the ups, the downs, the unexpected turns. So, here’s to your journey, whatever it looks like. Keep going, keep dreaming. It might not turn out the way you envisioned it, but it’s only impossible if you quit.
I am drafting this post at 35,000 feet flying back from Japan. I’ve entered the US about 30 times, but this will be the first time I’ll be using my shiny blue passport. No anxiety about aggressive questions, secondary inspection, or the possibility of deportation. A couple of days ago, my wife had her naturalization ceremony, and with her, our whole family is now American. This post is a reflecting on our 11-year immigration journey. My American Dream My story with technology started at 8, with my first computer. I fell in love and decided that one day I would start a computer business. And of course, it would have to be in Silicon Valley, the epicenter of innovation. I grew up influenced by the iconic Californian lifestyle of the 90s, from Tony Hawk to bands like Blink-182 and The Offspring, which only fueled my desire to call the West Coast home. As I finished my Computer Science studies, the reality of achieving my American dream seemed increasingly distant. My enthusiasm for the Californian way of life hadn’t waned — I had started surfing and I was even playing in a pop-punk band. But the immigration complexities were too daunting. It looked impossible. I decided to study a Master’s Degree in the UK and reinforce my English. Right before completing my degree in England, I was offered a six-month internship at a startup in San Francisco. Financially, it was not the smartest decision — I would barely be able to afford rent, despite having better paid options in Europe. However, experiencing Silicon Valley was a lifelong dream. It wasn’t an obvious choice. But I ultimately packed my suitcase, left behind my family, girlfriend and friends, and relocated across the world. Landing in California My journey in the U.S. began with a J1 visa, intended for interns and relatively simple to secure with an employer’s backing. It was a suitable fit for my six-month plan, extendable to a full year, without any ambition for a longer stay. Yet, I worked extremely hard, and the situation changed when I was introduced to the possibility of obtaining an H-1B visa. Unlike the J1, the H-1B visa demands wage parity with U.S. citizens, allows for a stay of up to six years, and paves the way for permanent residency. Most importantly, it meant I could start laying down roots in the US, such as building my credit score, buying a car, or negotiating a long-term lease. First Immigration Problems My living situation dramatically improved when I traded my small, rat-filled room for a two-bedroom apartment in the Outer Sunset, sharing the space with a friend. I got a sizeable salary bump. However, the happiness was short-lived. H-1B visa applications had exceeded available spots for the first time in years, introducing a lottery. My coding skills, education, and value to my employer wouldn’t factor into this gamble. Anxiety mounted for a very long month, as friends celebrated their visa wins. I was left in the dark, bracing for bad news. Against the odds, relief came just a day after a disheartening talk with my immigration lawyer, granting me my first taste of luck. Reuniting with my girlfriend Sick. My H-1B visa approval meant I could make the US my home for six additional years, longer than Marina and I had been dating. As she was about to end her studies, we strategized on ways to reunite in the US. Marrying earlier was an option, but with H-1B restrictions preventing spouses from working, we looked for alternatives. The easiest path forward involved securing a student visa, leading to an 12-month work permit, followed by an H-1B visa application. In the competitive climate of 2015, her work visa acceptance felt nothing short of miraculous, becoming our story’s second lucky strike. Permanent Residency While six years might seem long, they pass quickly when you are busy and having fun. Halfway through, it became clear we needed to strategize for the future when it was time to renew my visa. My employer agreed to initiate the Green Card application, a lengthy and costly process requiring proof that I was indispensable for the company. Despite the complexities, our attorney believed the case would progress smoothly, estimating an 18-month completion time. Surprisingly, the initial phase went way faster than anticipated, prompting our attorney to suggest an immediate wedding for Marina and me, a necessary step to include her in the Green Card application. We quickly scheduled our wedding at the Spanish Consulate in San Francisco, departing from our original plan for a ceremony in Spain. More problems A year and a half in, expecting our Green Cards, we faced an unexpected challenge: our marriage, officiated at a consulate, was not recognized by US Immigration, compelling us to marry again, pay the associated fees again, and start the process over. This development was extremely frustrating, specially as my friend Jacob and I were contemplating founding a company, and the absence of a Green Card meant remaining as an employee. To rectify the situation, we promptly got remarried at San Mateo City Hall, choosing it for its rapid scheduling. Two months later we held another ceremony in Spain with our family and friends (our third marriage overall). The delay in our reapplication, exacerbated by the recent election of Trump and a subsequent slowdown in immigration services, led us into a stressful period of uncertainty. Our inability to make definite plans, from household purchases to housing arrangements left us anxiously awaiting any news on our application. As we navigated this uncertainty, the possibility of dedicating myself fully to our startup (later named RevenueCat) became increasingly dim. Going All In A pivotal moment came when our now startup, RevenueCat, was accepted into Y Combinator, requiring my full-time commitment. A big challenge due to my pending Green Card application. My immigration status became the biggest risk to our startup, even before launching. In searching for a solution, we identified a potential hack: an immigration loophole that allowed for employment changes under specific circumstances. It wasn’t risk free. There were no guarantees, and it involved giving up my H-1B status and the ability to travel. Should my Green Card application face rejection for any reason, I would instantly become an illegal immigrant. Deciding to take the gamble, we prepared the necessary documentation. To support our case, Jacob, my co-founder, had to write a letter stating that although my compensation was on the lower side, his, in the CEO role, was even lower. We also had to declare our company’s annual earnings ($0 at that time), and I suggested Jacob to specify it as less than $1 million. You should never lie to Homeland Security 😅. This leap of faith paid off; eight months later, we received our Green Card interview, where the immigration officer, making fun of our unique circumstances, granted approval on the spot. The Decision to Become American Those with an employment-based Green Card need a five-year stay in the US, compliant with all laws and tax requirements, to qualify for citizenship. While obtaining citizenship is not mandatory, and one might choose to stay a permanent resident indefinitely, citizenship confers full rights and responsibilities. Among these, the requirement to pay federal taxes forever, a big concern for many. If RevenueCat succeeds as we hope, I’m looking at significant tax payments, even if we end up moving back to Europe. The decision to embrace US citizenship came down to a simple reason: we can. We recognize the privilege of this choice, acknowledging the series of fortunate events that brought us here, aware that our journey could have taken decades had we originated from countries like India or China. Our twin daughters are blessed with dual citizenship, offering them a breadth of choices for their future. The opportunities the US has presented to our family are beyond what we once could dream. By becoming citizens, we gain a voice to influence immigration policies positively instead of blocking progress. My tax contributions have already reached the seven-figure mark. The continuation of our tax obligation is a small price to pay. And after all, there are some advantageous double taxation agreements 😉. Special thanks to my family for always supporting me and pushing me to live my dream in San Francisco. To Marina, my now wife, for joining me in this crazy adventure across the globe. To everyone at StepOne for running an amazing internship program. To Jesse, for believing in my potential and tackling the immigration challenges with me. And to my co-founder Jacob, for pushing me to take a leap of faith with my immigration status.
Since reading ‘High Growth Handbook’ by Elad Gil, the value of writing a ‘Working with’ document became crystal clear to me. I am sharing mine externally to inspire other founders and leaders to reflect and write down their own working styles. These documents are incredibly beneficial, especially in a multi-timezone, remote setting like we have at RevenueCat. I’ve spent some time fine-tuning mine, and this is the updated version. Welcome to your go-to manual for understanding how to collaborate effectively with me. My Mindset: Logic-Driven, Plan-Oriented I’m a logical thinker, much like a computer. If A implies B and we have A, I’ll typically conclude B. Sticking to plans and predictability is my comfort zone, yet I value reactivity, especially when customer-related issues arise and are solvable. This company isn’t just a job for me; it’s my life’s work. I’m deeply invested in everything here — our technology, culture, team, and customers. I get inspired and energized by hard-working coworkers who believe in our mission even more than me. As a co-founder, I can offer a wealth of institutional knowledge and guidance. While I may not have all the answers, I’m usually good at pointing you in the right direction. RevenueCat is only a sum of it’s parts. Our teammates drive our culture and I want to make sure we are building a place that people want to be. If you have a suggestion on how to make RevenueCat an even cooler place to work for our teammates I’m always here to talk about it. How We’ll Operate Regular Check-ins: For my direct reports, expect weekly or bi-weekly one-on-one meetings. To make our discussions more focused, I prefer that we establish an agenda before our scheduled time together. Communication Protocols: My schedule doesn’t allow much room for impromptu calls. If something urgent pops up, message me on Slack first. Should it require a call, schedule it through Susannah, please never bypass her. Meeting Preparation: Come to meetings with an agenda to ensure productivity. Without one, I might dominate the conversation, potentially missing your crucial points. Let’s both be responsible for following up on action items. Team Support: I’m open to joining other team meetings, but please share the agenda in advance and mark my attendance as optional unless crucial. Problem-Solving Approach: My engineering background means I love tackling complex problems using a divide and conquer approach: by breaking them down into smaller, manageable chunks, solving each piece, and then combining them for a final solution. If we can improve a completely broken system to 90% functionality, that’s significant progress in my book! Communication Style Note-Taking: While I take meticulous notes, my current preferred tool doesn’t support sharing. If you wish to access these notes, it’s on you to set up a shared document in Google Docs, Notion, or Lattice. Information Filtering: I prefer having complete transparency and the ability to filter out unnecessary details myself. Always explicitly state if you need input from me, or else I’ll assume it’s for my information only. Feedback Style: Expect direct feedback from me. I’ll clearly differentiate between areas for improvement and significant performance concerns. Trust Dynamics: Consider my trust like a metaphorical ‘bucket’ that starts half-full for everyone and adjusts based on your actions. The more you fill this bucket, the more autonomy you’ll have. For Managers Transparency in Challenges: Startups are always broken one way or another. I prefer to hear any bad news about a project or a team member directly from you. Working together through challenges can strengthen our trust and working relationship. Progress and Concerns: During our 1:1’s, I’ll inquire about your team dynamics and direct reports’ progress. I encourage you to include any details in our 1:1 agenda and lead the conversation to address any performance concerns, project delays or notable achievements . Feedback Dynamics: I recognize the weight of my title. To avoid unnecessary tension, I prefer to provide critical feedback about your reports directly to you so you can address privately. On the other hand, if there is any commendable achievement by your team I will do my best to praise publicly. If you feel there is someone on your team that I should connect with or praise, please let me know. Encouraging our team and recognizing their strengths is something that is very important to me. Preferences and Pet Peeves What I like Doing your homework: No question is stupid, but always do your initial research before distracting the team. Being resolutive: Getting things done, unblocking yourself. Readable and consistent code. Proven, boring technology over unproven open source projects that is trending on Hacker News. Proactivity: See a problem? Fix it right away before anyone notices. Made a mistake? Build systems to prevent anyone else making the same one again. Double checking your work: Give your work (documents, presentations, pull requests) a quick self-review before presenting it to the team. Transparency: In a multi-tz, remote environment, over-communication is better than miscommunication. Healthy discussions. When there is a decision to make that is not clear, it’s because all the different approaches have pros and cons. Together we will be able to calibrate and choose the lesser evil. A short call (or loom) is preferred over constant Slack interruptions. What I don’t like Gossip and rumors: They destroy the culture. Be upfront. Cargo cult: Let’s not do something just because BIG CO does it. That’s the beauty of building something from scratch. Unnecessary blockers. You’re all pretty smart here! Always try to unblock yourself first. Lack of context in questions, emails, and discussions. Not speaking up when something isn’t clear. Recurrent mistakes or questions: One time, it’s totally expected. Two times, hmm. Three times, nah. Learn, document, and build systems. Complaining without taking any action to improve the situation. Sarcasm or other ways of communication violence during disagreements: When somebody wins an argument, most of the time, the whole team loses. Acknowledging My Flaws Overcommitment: I tend to take on more than I should, which inevitably affects my focus. While I’m working on this, please understand if I occasionally get sidetracked by emergencies. Communication while Debugging: When addressing issues, I might share unvalidated hypotheses, which can be confusing. I’m learning to communicate more clearly and only after verifying my thoughts. Problem-Solving Obsession: Unsolved problems keep me up at night, which isn’t ideal for my well-being. It’s a habit I’m aware of and trying to balance. Pessimistic Tendencies: In evaluating problems, I often veer towards catastrophic thinking rather than optimism, a trait I’m mindful of and trying to moderate. Office Hours To maximize my availability given my tight schedule, I’ve introduced ‘office hours.’ This time is open for anyone to schedule a 15-minute chat with me about any concerns or ideas you might have. Reach out to Susannah for scheduling details. Thanks for sticking with me till the end! These are my personal preferences, not commandments carved in stone. I’m stoked to collaborate, build awesome stuff, and, above all, have fun together!
Another year as a founder CTO, and let me tell you, it’s been one for the books. I can’t remember a time in my life that was more demanding and emotionally draining. Those early years were filled with hard work, but we were also full of energy, ambition to build, and the sense that we had absolutely nothing to lose. As my dear friend Jacob used to quip, “Worst case scenario nobody dies”. Yet, everything takes on a new perspective when you’re responsible for the monetization infrastructure of over 30,000 apps and ensuring the livelihoods of not only your team but also your own family. While I would typically begin this series of posts with an array of metrics, this year has been a whirlwind of events that has taken precedence over mere numbers. So, dear friend, take a seat and allow me to share with you a deeply personal and epic firefighting tale and the battle to restore the flame of RevenueCat’s core values. The Year of Shipping We embarked on Q1 with big intentions and an ambitious roadmap. With seven new engineering teams, my role was to lead the one responsible for serving our larger customers. My days consisted of collaborating with our (still tiny) sales team, while simultaneously overseeing our support function. While I continued to provide technical guidance to several projects, I made the conscious decision to delegate the bulk of product development to the other teams. In hindsight, this decision proved to be a mistake. The teams were still finding their footing, with a mix of new hires, and there was a disconnect between engineering and product that needed addressing — a topic we’ll get into later. Nevertheless, the team I led was firing on all cylinders, delivering enterprise-level features at a hasty pace. From implementing single-sign-on in a matter of days, to tackling gnarly bugs, this team’s momentum was inspiring. I hoped that this stride would serve as a catalyst, motivating the rest of the teams to achieve a similar velocity. On the home front, my wife’s parental leave came to an end in January, marking the start of a new era where my hours were no longer flexible. Together, we embarked on the demanding task of caring for our twin babies. Little did I know how much the lack of sleep would impact me. Fatigue began to set in and my usual escape valves, such as surfing, turned into distant memories. Caffeine became my closest friend, helping me stay awake as I navigated the demands of work and family. I would spend my entire weekends lying in bed, trying to recover. I wrongly assumed it would be a short phase. Troubles never come alone On the fateful morning of March 9th, while I was soothing one of our crying babies at 4:30 AM, my WhatsApp began buzzing with messages from concerned fellow founders. Rumors were swirling that Silicon Valley Bank, the custodian of most VC-backed startup funds, was about to collapse. Within hours these whispers escalated into a full-blown bank run and we found ourselves unable to access our funds. Without going into the nitty-gritty details, it was an intensely stressful weekend. We were on the verge of a payroll crisis and we didn’t even have a functioning bank to transact with. However, we couldn’t afford to let this situation be what killed RevenueCat. We worked to expedite the opening of new bank accounts and explored multiple liquidity alternatives. Fortunately, we were privileged enough to entertain multiple options. One investor came to help, wiring funds from their personal account, and some of our loyal customers offered to pay in advance. Just as hope seemed to dwindle, the FDIC announced that they would guarantee all deposits on that Sunday afternoon. Crisis averted. Emotionally drained from the weekend’s trauma, we received another unexpected blow just a few days later: Y Combinator was discontinuing its Continuity Fund. This created a dilemma regarding the fate of their board seat, something we would have never anticipated. Just weeks prior, we had suffered a severe outage caused by our cloud provider. We tried to console ourselves, thinking, “At least all these problems are internal; we’re not dealing with downtime”. A Crisis of Reliability Our break was short-lived. Less than a week after the Silicon Valley Bank fiasco we experienced yet another major outage, and this time, it was self-inflicted. When you’re handling hundreds of thousands of API requests per second, even a few seconds of downtime can set off a cascade of alarms and potential sales losses. Our customers were understandably frustrated, and they didn’t hesitate to make their displeasure known through every available channel. It was heartbreaking to witness and I felt a deep sense of personal failure. This marked the third user-facing issue in a matter of months. It wasn’t something to sweep under the rug: our reputation was on the line and it was time to act. By this point, I was utterly sleep-deprived and my Apple Watch had begun sending me concerning health notifications. The day after we resolved the outage, my co-founder Jacob and I came up with an action plan. It was officially wartime. We needed to act decisively. We publicly unveiled our plan: to develop a robust fallback system independent of our current infrastructure. And we promised to deliver it within a week. Simultaneously, Jacob and I embarked on an apology tour, reaching out personally to some of our most worried customers. This was a painful but humbling experience for us, but it proved beneficial on multiple fronts. It allowed us to reiterate our commitment to becoming the best in-app subscription infrastructure provider in the world while gaining invaluable insights into our customers’ pain points. RC Fortress I rallied a small crew of engineers from different teams to build the first version of what we called “RevenueCat Fortress”. This component was designed to make sure end-customers could purchase seamlessly, even when our main servers were unavailable. It was a crazy week because we set ourselves a tight deadline but it helped boost our spirits and proved we could deliver software fast. The initial version of RevenueCat Fortress was quite simple – it operated behind the scenes on the server. But we didn’t stop there. We made it even better in the next iterations by adding SDK improvements such as offline entitlements. When it finally rolled out, it did so with flying colors. We even got to put it to the test during a major Apple outage and it saved the day for RevenueCat customers, making them immune to Apple’s downtime. Turning things around Looking back, the birth of RC Fortress marked the start of a shift in our culture. It got us back to the basics of reliability, fast delivery, and customer obsession. We couldn’t afford to spend months on extensive, untested projects. We had to rapidly build the features our customers valued most and iterate from there. We also realized that keeping things rock-solid wasn’t just the infrastructure team’s job; it was a global effort. Around the same time, we faced a couple of setbacks when we parted ways with two executives – the VP of People and the VP of Engineering. We tried to find a new VP of Engineering but couldn’t find a match that really excited us. So, the board agreed it would be best if I took the reins of the entire engineering organization again. Those days gave me a chance to get closer to the product teams again. Here’s where I spent most of my energy: Performance: I clarified expectations, provided feedback, and coached managers on performance management. Hiring: We tweaked our hiring process and re-calibrated interviewers’ expectations. Reliability and Quality: We were pretty good at doing post-mortems after issues but we had too many of them. They lacked detail and they weren’t followed through with action items. We needed a little bit of a cultural reset. We introduced dedicated incident Slack channels and clearly defined roles. Customer Obsession: Taking over the support team was eye-opening. It gave me a direct line to our product’s weak spots and what confused our customers. We started categorizing support tickets and sending them straight to the right product teams for triaging. Project Management: We focused on breaking projects into smaller chunks to deliver faster, instead of getting lost in never-ending projects. Education and Best Practices: I spent time educating other departments, especially post-sales teams, to avoid recurring mistakes that were slowing down our engineering progress. On top of all that, I reconnected with our customers more than ever. I hopped on planes to visit them at their offices and even worked our booth at a few conferences. It was a refreshing change to chat with users face-to-face, and hearing their unique challenges in person after a long time. Life is what happens when you’re busy running your startup We were fortunate enough to fly in my mother-in-law to assist with our babies, which made my travel plans possible. I finally felt more rested and even managed to squeeze in a few surfing sessions. Things were looking up both personally and professionally. I was eagerly anticipating our annual company-wide offsite, especially since I had missed most of the previous one due to my wife’s high-risk pregnancy. This time around I was geared up to address the entire engineering team, sharing the exciting changes and boosting morale. We were about to start winning again. But then, the day before my flight, I received a call from my father back in Spain. My mother had been rushed to the hospital, and she had been diagnosed with an extremely aggressive form of leukemia. Time seemed to stand still. I boarded the flight as planned, chugged two Red Bulls, and delivered that motivational talk to the whole team, while my mom was in a hospital bed thousands of miles away. This was hands down the toughest thing I’ve ever done as a startup founder. I left the offsite early and headed back to my hometown. Over the following weeks, I traveled back and forth around the globe, coordinating with my family. Sadly, my mother never left the hospital, she passed away merely a few weeks after the diagnosis. These are the things that always lurk in the back of your mind when you’re living 10,000 miles away from home, but you never truly believe they’ll happen. Until they do, and they shatter you. Keep on pushing The days that followed were far from easy. We were dealing with the launch of our biggest customer’s app, something we’d been preparing for a long time. The scale was enormous and the hard work of our team truly paid off. Our systems ran incredibly smoothly. It was a monumental victory, especially after the rocky start to the year. But, mentally, I wasn’t prepared to savor the moment. Yet, the energy post-offsite was infectious. People genuinely enjoyed meeting each other in real life and were fired up to start shipping. We couldn’t let this opportunity slip through our fingers. I paid homage to my mom’s teachings by continuing to press forward. RC Paywalls One of the major product ideas that had always been on our team’s wishlist was paywalls. We hadn’t tackled it because it seemed daunting and we lacked a product team with all the necessary skills. We couldn’t even estimate how long it would take to build. But, fueled by the success of RC Fortress, we decided to take a shot at it. We assembled a small team with members borrowed from different corners of the company. We didn’t mess with any reporting structures but appointed a leader. We went back to our roots, working in a hackathon-style frenzy for a couple of weeks to build a prototype. Just like in the good old days. And, boy, did the team rise to the occasion. We gave them some extra time and, in the end, they delivered one of our biggest product wins of the year. Shipping paywalls felt like a breath of fresh air and a clear sign that we still had our mojo. We were still capable of shipping software at lightning speed and keeping our customers excited. Based on all these lessons, the Head of Product and I started cooking up a brand new way of building products at RevenueCat. Engineering/Product/Design changes The complete process overhaul would warrant a couple of blog posts, but let me highlight the key changes to our workflow: We’ve reviewed all existing teams to determine whether they should continue as is, be replaced, or undergo changes in their mission or structure. We’ve rebalanced and clarified the responsibilities across Product, Engineering, and Design: Engineering takes the lead on feasibility, delivery, and developer experience, managing Linear, and overseeing technical architecture (and debt) roadmaps. Product is dedicated to customer value, business viability, and collaboration with sales and marketing teams. They also provide support to engineering in refining project scopes. Design is responsible for usability. We’ve formalized the role of Tech Lead, assigning them as the Directly Responsible Individuals for specific projects. They’re accountable for project success, with full backing from their Engineering Manager. It’s optional and project-dependent and doesn’t entail a title or salary change. We’ve acknowledged the need for engineering-driven initiatives, where PM and Design are involved on an as-needed basis. For projects with dependencies with other teams, we’ll designate a team member from the collaborating team as a formal interface. Our existing setup of stable product teams will remain the norm for most of our work. Temporary project teams will be established only when there’s a strong need for cross-team collaboration over a limited period. We’ll conduct monthly roadmap and shipping reviews with the founders and Head of Product. These reviews will provide insights into what we’re building, offer feedback opportunities, and help identify cross-functional dependencies and misalignments. 2024: The year of shipping + selling Collaborating with the Product team showcased the immense benefits of working closely together. Traditionally, Product reported directly to our CEO, which introduced unnecessary layers of indirection. In light of this and our recent addition of a VP of Sales, we decided it was time for a reorganization. Currently, Jacob (co-founder, and CEO), is overseeing Go to Market, People, and Operations, while I’m responsible for Engineering, Product, and Customer Engineering. We’ve brought in a VP of Customer Engineering, who reports to me and is in charge of Support and Technical Account Management. With our current headcount at 73 employees, my organization consists of 48 team members. Our executive team developed the most comprehensive planning effort to date. Our goal is to accelerate growth, focusing on sales and product delivery. We will avoid distractions by being extremely strategic at hiring. The past quarter showcased the strength of our engineering and product teams. New team members have been onboarded successfully, contributing meaningfully, and our management structure is finally robust. It took a bit of time for the “year of shipping” to fully materialize, nearly a year later, but customers have taken notice and we’re capitalizing on this momentum. On the enterprise sales front, I’m extremely bullish. We’ve secured the biggest deals in the company’s history. RevenueCat has evolved beyond being a product just for indie developers. However, we acknowledge the need to continue closing the product-market fit gap for enterprise clients. We’ve gained valuable insights into enterprise needs, and we’ll keep developing new products and features tailored to them. Indie developers will also take advantage of them to make more money. In 2024, the collaboration between our go-to-market and engineering teams will be critical. Highlights This year, as you’ve probably noticed, was a tough one. However, besides the challenges, there were several remarkable achievements to celebrate: We truly shipped. Our second hackathon, spanning an entire week, was an epic success. Many of the projects launched immediately, directly benefiting our customers. We had the privilege of collaborating with prominent brands and companies, including none other than Arnold Schwarzenegger himself. We created an astonishing amount of high-quality content. Our SubClub podcast outperformed all my expectations. During the chaos of the bank run, we discovered that one of our idols was not only a RevenueCat customer but also a devoted fan. We experimented with fresh team topologies and processes, and they turned out to be successful. We fine-tuned our vision for building a winning team, offering improved feedback, clearer expectations, and timely performance management. Jacob and I are no longer the sole authorities on Apple and Google subscriptions within the company. We successfully recruited seasoned executives to join our team. Our core infrastructure team accomplished monumental feats. We now support over 1 billion API requests daily, transitioned to our own data platform, and developed our own memcached client. All while maintaining flat costs despite the increase in load. Learnings It’s impossible to achieve peak performance without attention to health, exercise, and sleep. I’m no longer in my twenties. Complexity is the root of all evil. Startups and software are inherently complex, so avoid introducing unnecessary complexity. Begin by building the simplest feature or process, debug it, and then iterate as needed. Starting a business is tough, but launching a remote startup is an even greater challenge. Scaling a remote startup while parenting two under two is a herculean effort. Building a brand takes years but its reputation can be destroyed in an instant. Protect the integrity of your brand at all costs. Every new team member should add value, and especially so in a startup. Some provide immense leverage, while others become bottlenecks. The trickiest are those in the middle, who often end up becoming bottlenecks. Founders usually spot this within the first few weeks. Letting someone go is a taxing task. Even when managers believe it’s the right thing to do, it often requires a significant amount of support and guidance. Transparency in times of crisis pays dividends. Employees want to be treated like adults, and it builds trust. The same applies externally. Early worries often become baseless. By the time they become actual problems, your company might have died, you might have gained experience, or you might have hired the right talent to tackle them. SOC 2 auditors may request unconventional supporting evidence, such as employee performance reviews. Developers love socks. I’m so fortunate to have the world’s best co-founder. At this stage, my role is much more aligned with that of a founder than a traditional CTO or VP of Engineering. I continue to address issues as if they were technical problems, but my responsibilities extend well beyond the technology area. Life keeps moving forward, with its share of highs and lows. Life is too short, so you have to ensure the journey remains fun. For me, that means working with people who inspire me, and serving customers I genuinely care about. I really hope you enjoyed reading this post. I’m aware it’s a lot longer than my previous ones, but there were so many stories to share. As always, my intention was to share it with complete honesty and transparency, avoiding the hype that often surrounds startups. If you are facing similar challenges and want to connect and share experiences, please do not hesitate to reach out on Twitter or shoot me an email! Special thanks to my co-founder Jacob, the whole RevenueCat team, and our valuable customers. I also need to express my eternal gratitude to all the CTOs and leaders who have been kind enough to share their experiences over these years. Shoutout to Dani Lopez, Peter Silberman, Alex Plugaru, Kwindla Hultman Kramer, João Batalha, Karri Saarinen, Miguel Martinez Triviño, Sam Lown, Javi Santana, Pau Ramón, Javier Maestro, Matias Woloski, Tobias Balling, Jason Warner, and Will Larson. Our investors and early believers Jason Lemkin, Anu Hariharan, Mark Fiorentino, Mark Goldberg, Andrew Maguire, Gustaf Alströmer, and Nico Wittenborn. I want to convey my deep gratitude to my amazing wife, Marina, who has been my unwavering source of inspiration and support from the very beginning, and for blessing us with our two precious daughters. I cannot close this post without thanking my mom, who made countless sacrifices to mold me into the person I am today. I promise you will look down on us with pride the day we ring the bell in New York. I love you dearly.
More in programming
We received over 2,200 applications for our just-closed junior programmer opening, and now we're going through all of them by hand and by human. No AI screening here. It's a lot of work, but we have a great team who take the work seriously, so in a few weeks, we'll be able to invite a group of finalists to the next phase. This highlights the folly of thinking that what it'll take to land a job like this is some specific list of criteria, though. Yes, you have to present a baseline of relevant markers to even get into consideration, like a great cover letter that doesn't smell like AI slop, promising projects or work experience or educational background, etc. But to actually get the job, you have to be the best of the ones who've applied! It sounds self-evident, maybe, but I see questions time and again about it, so it must not be. Almost every job opening is grading applicants on the curve of everyone who has applied. And the best candidate of the lot gets the job. You can't quantify what that looks like in advance. I'm excited to see who makes it to the final stage. I already hear early whispers that we got some exceptional applicants in this round. It would be great to help counter the narrative that this industry no longer needs juniors. That's simply retarded. However good AI gets, we're always going to need people who know the ins and outs of what the machine comes up with. Maybe not as many, maybe not in the same roles, but it's truly utopian thinking that mankind won't need people capable of vetting the work done by AI in five minutes.
Recently I got a question on formal methods1: how does it help to mathematically model systems when the system requirements are constantly changing? It doesn't make sense to spend a lot of time proving a design works, and then deliver the product and find out it's not at all what the client needs. As the saying goes, the hard part is "building the right thing", not "building the thing right". One possible response: "why write tests"? You shouldn't write tests, especially lots of unit tests ahead of time, if you might just throw them all away when the requirements change. This is a bad response because we all know the difference between writing tests and formal methods: testing is easy and FM is hard. Testing requires low cost for moderate correctness, FM requires high(ish) cost for high correctness. And when requirements are constantly changing, "high(ish) cost" isn't affordable and "high correctness" isn't worthwhile, because a kinda-okay solution that solves a customer's problem is infinitely better than a solid solution that doesn't. But eventually you get something that solves the problem, and what then? Most of us don't work for Google, we can't axe features and products on a whim. If the client is happy with your solution, you are expected to support it. It should work when your customers run into new edge cases, or migrate all their computers to the next OS version, or expand into a market with shoddy internet. It should work when 10x as many customers are using 10x as many features. It should work when you add new features that come into conflict. And just as importantly, it should never stop solving their problem. Canonical example: your feature involves processing requested tasks synchronously. At scale, this doesn't work, so to improve latency you make it asynchronous. Now it's eventually consistent, but your customers were depending on it being always consistent. Now it no longer does what they need, and has stopped solving their problems. Every successful requirement met spawns a new requirement: "keep this working". That requirement is permanent, or close enough to decide our long-term strategy. It takes active investment to keep a feature behaving the same as the world around it changes. (Is this all a pretentious of way of saying "software maintenance is hard?" Maybe!) Phase changes In physics there's a concept of a phase transition. To raise the temperature of a gram of liquid water by 1° C, you have to add 4.184 joules of energy.2 This continues until you raise it to 100°C, then it stops. After you've added two thousand joules to that gram, it suddenly turns into steam. The energy of the system changes continuously but the form, or phase, changes discretely. Software isn't physics but the idea works as a metaphor. A certain architecture handles a certain level of load, and past that you need a new architecture. Or a bunch of similar features are independently hardcoded until the system becomes too messy to understand, you remodel the internals into something unified and extendable. etc etc etc. It's doesn't have to be totally discrete phase transition, but there's definitely a "before" and "after" in the system form. Phase changes tend to lead to more intricacy/complexity in the system, meaning it's likely that a phase change will introduce new bugs into existing behaviors. Take the synchronous vs asynchronous case. A very simple toy model of synchronous updates would be Set(key, val), which updates data[key] to val.3 A model of asynchronous updates would be AsyncSet(key, val, priority) adds a (key, val, priority, server_time()) tuple to a tasks set, and then another process asynchronously pulls a tuple (ordered by highest priority, then earliest time) and calls Set(key, val). Here are some properties the client may need preserved as a requirement: If AsyncSet(key, val, _, _) is called, then eventually db[key] = val (possibly violated if higher-priority tasks keep coming in) If someone calls AsyncSet(key1, val1, low) and then AsyncSet(key2, val2, low), they should see the first update and then the second (linearizability, possibly violated if the requests go to different servers with different clock times) If someone calls AsyncSet(key, val, _) and immediately reads db[key] they should get val (obviously violated, though the client may accept a slightly weaker property) If the new system doesn't satisfy an existing customer requirement, it's prudent to fix the bug before releasing the new system. The customer doesn't notice or care that your system underwent a phase change. They'll just see that one day your product solves their problems, and the next day it suddenly doesn't. This is one of the most common applications of formal methods. Both of those systems, and every one of those properties, is formally specifiable in a specification language. We can then automatically check that the new system satisfies the existing properties, and from there do things like automatically generate test suites. This does take a lot of work, so if your requirements are constantly changing, FM may not be worth the investment. But eventually requirements stop changing, and then you're stuck with them forever. That's where models shine. As always, I'm using formal methods to mean the subdiscipline of formal specification of designs, leaving out the formal verification of code. Mostly because "formal specification" is really awkward to say. ↩ Also called a "calorie". The US "dietary Calorie" is actually a kilocalorie. ↩ This is all directly translatable to a TLA+ specification, I'm just describing it in English to avoid paying the syntax tax ↩
While Stripe is a widely admired company for things like its creation of the Sorbet typer project, I personally think that Stripe’s most interesting strategy work is also among its most subtle: its willingness to significantly prioritize API stability. This strategy is almost invisible externally. Internally, discussions around it were frequent and detailed, but mostly confined to dedicated API design conversations. API stability isn’t just a technical design quirk, it’s a foundational decision in an API-driven business, and I believe it is one of the unsung heroes of Stripe’s business success. This is an exploratory, draft chapter for a book on engineering strategy that I’m brainstorming in #eng-strategy-book. As such, some of the links go to other draft chapters, both published drafts and very early, unpublished drafts. Reading this document To apply this strategy, start at the top with Policy. To understand the thinking behind this strategy, read sections in reverse order, starting with Explore. More detail on this structure in Making a readable Engineering Strategy document. Policy & Operation Our policies for managing API changes are: Design for long API lifetime. APIs are not inherently durable. Instead we have to design thoughtfully to ensure they can support change. When designing a new API, build a test application that doesn’t use this API, then migrate to the new API. Consider how integrations might evolve as applications change. Perform these migrations yourself to understand potential friction with your API. Then think about the future changes that we might want to implement on our end. How would those changes impact the API, and how would they impact the application you’ve developed. At this point, take your API to API Review for initial approval as described below. Following that approval, identify a handful of early adopter companies who can place additional pressure on your API design, and test with them before releasing the final, stable API. All new and modified APIs must be approved by API Review. API changes may not be enabled for customers prior to API Review approval. Change requests should be sent to api-review email group. For examples of prior art, review the api-review archive for prior requests and the feedback they received. All requests must include a written proposal. Most requests will be approved asynchronously by a member of API Review. Complex or controversial proposals will require live discussions to ensure API Review members have sufficient context before making a decision. We never deprecate APIs without an unavoidable requirement to do so. Even if it’s technically expensive to maintain support, we incur that support cost. To be explicit, we define API deprecation as any change that would require customers to modify an existing integration. If such a change were to be approved as an exception to this policy, it must first be approved by the API Review, followed by our CEO. One example where we granted an exception was the deprecation of TLS 1.2 support due to PCI compliance obligations. When significant new functionality is required, we add a new API. For example, we created /v1/subscriptions to support those workflows rather than extending /v1/charges to add subscriptions support. With the benefit of hindsight, a good example of this policy in action was the introduction of the Payment Intents APIs to maintain compliance with Europe’s Strong Customer Authentication requirements. Even in that case the charge API continued to work as it did previously, albeit only for non-European Union payments. We manage this policy’s implied technical debt via an API translation layer. We release changed APIs into versions, tracked in our API version changelog. However, we only maintain one implementation internally, which is the implementation of the latest version of the API. On top of that implementation, a series of version transformations are maintained, which allow us to support prior versions without maintaining them directly. While this approach doesn’t eliminate the overhead of supporting multiple API versions, it significantly reduces complexity by enabling us to maintain just a single, modern implementation internally. All API modifications must also update the version transformation layers to allow the new version to coexist peacefully with prior versions. In the future, SDKs may allow us to soften this policy. While a significant number of our customers have direct integrations with our APIs, that number has dropped significantly over time. Instead, most new integrations are performed via one of our official API SDKs. We believe that in the future, it may be possible for us to make more backwards incompatible changes because we can absorb the complexity of migrations into the SDKs we provide. That is certainly not the case yet today. Diagnosis Our diagnosis of the impact on API changes and deprecation on our business is: If you are a small startup composed of mostly engineers, integrating a new payments API seems easy. However, for a small business without dedicated engineers—or a larger enterprise involving numerous stakeholders—handling external API changes can be particularly challenging. Even if this is only marginally true, we’ve modeled the impact of minimizing API changes on long-term revenue growth, and it has a significant impact, unlocking our ability to benefit from other churn reduction work. While we believe API instability directly creates churn, we also believe that API stability directly retains customers by increasing the migration overhead even if they wanted to change providers. Without an API change forcing them to change their integration, we believe that hypergrowth customers are particularly unlikely to change payments API providers absent a concrete motivation like an API change or a payment plan change. We are aware of relatively few companies that provide long-term API stability in general, and particularly few for complex, dynamic areas like payments APIs. We can’t assume that companies that make API changes are ill-informed. Rather it appears that they experience a meaningful technical debt tradeoff between the API provider and API consumers, and aren’t willing to consistently absorb that technical debt internally. Future compliance or security requirements—along the lines of our upgrade from TLS 1.2 to TLS 1.3 for PCI—may necessitate API changes. There may also be new tradeoffs exposed as we enter new markets with their own compliance regimes. However, we have limited ability to predict these changes at this point.
I like the job title “Design Engineer”. When required to label myself, I feel partial to that term (I should, I’ve written about it enough). Lately I’ve felt like the term is becoming more mainstream which, don’t get me wrong, is a good thing. I appreciate the diversification of job titles, especially ones that look to stand in the middle between two binaries. But — and I admit this is a me issue — once a title starts becoming mainstream, I want to use it less and less. I was never totally sure why I felt this way. Shouldn’t I be happy a title I prefer is gaining acceptance and understanding? Do I just want to rebel against being labeled? Why do I feel this way? These were the thoughts simmering in the back of my head when I came across an interview with the comedian Brian Regan where he talks about his own penchant for not wanting to be easily defined: I’ve tried over the years to write away from how people are starting to define me. As soon as I start feeling like people are saying “this is what you do” then I would be like “Alright, I don't want to be just that. I want to be more interesting. I want to have more perspectives.” [For example] I used to crouch around on stage all the time and people would go “Oh, he’s the guy who crouches around back and forth.” And I’m like, “I’ll show them, I will stand erect! Now what are you going to say?” And then they would go “You’re the guy who always feels stupid.” So I started [doing other things]. He continues, wondering aloud whether this aversion to not being easily defined has actually hurt his career in terms of commercial growth: I never wanted to be something you could easily define. I think, in some ways, that it’s held me back. I have a nice following, but I’m not huge. There are people who are huge, who are great, and deserve to be huge. I’ve never had that and sometimes I wonder, ”Well maybe it’s because I purposely don’t want to be a particular thing you can advertise or push.” That struck a chord with me. It puts into words my current feelings towards the job title “Design Engineer” — or any job title for that matter. Seven or so years ago, I would’ve enthusiastically said, “I’m a Design Engineer!” To which many folks would’ve said, “What’s that?” But today I hesitate. If I say “I’m a Design Engineer” there are less follow up questions. Now-a-days that title elicits less questions and more (presumed) certainty. I think I enjoy a title that elicits a “What’s that?” response, which allows me to explain myself in more than two or three words, without being put in a box. But once a title becomes mainstream, once people begin to assume they know what it means, I don’t like it anymore (speaking for myself, personally). As Brian says, I like to be difficult to define. I want to have more perspectives. I like a title that befuddles, that doesn’t provide a presumed sense of certainty about who I am and what I do. And I get it, that runs counter to the very purpose of a job title which is why I don’t think it’s good for your career to have the attitude I do, lol. I think my own career evolution has gone something like what Brian describes: Them: “Oh you’re a Designer? So you make mock-ups in Photoshop and somebody else implements them.” Me: “I’ll show them, I’ll implement them myself! Now what are you gonna do?” Them: “Oh, so you’re a Design Engineer? You design and build user interfaces on the front-end.” Me: “I’ll show them, I’ll write a Node server and setup a database that powers my designs and interactions on the front-end. Now what are they gonna do?” Them: “Oh, well, we I’m not sure we have a term for that yet, maybe Full-stack Design Engineer?” Me: “Oh yeah? I’ll frame up a user problem, interface with stakeholders, explore the solution space with static designs and prototypes, implement a high-fidelity solution, and then be involved in testing, measuring, and refining said solution. What are you gonna call that?” [As you can see, I have some personal issues I need to work through…] As Brian says, I want to be more interesting. I want to have more perspectives. I want to be something that’s not so easily definable, something you can’t sum up in two or three words. I’ve felt this tension my whole career making stuff for the web. I think it has led me to work on smaller teams where boundaries are much more permeable and crossing them is encouraged rather than discouraged. All that said, I get it. I get why titles are useful in certain contexts (corporate hierarchies, recruiting, etc.) where you’re trying to take something as complicated and nuanced as an individual human beings and reduce them to labels that can be categorized in a database. I find myself avoiding those contexts where so much emphasis is placed in the usefulness of those labels. “I’ve never wanted to be something you could easily define” stands at odds with the corporate attitude of, “Here’s the job req. for the role (i.e. cog) we’re looking for.” Email · Mastodon · Bluesky
I've been biking in Brooklyn for a few years now! It's hard for me to believe it, but I'm now one of the people other bicyclists ask questions to now. I decided to make a zine that answers the most common of those questions: Bike Brooklyn! is a zine that touches on everything I wish I knew when I started biking in Brooklyn. A lot of this information can be found in other resources, but I wanted to collect it in one place. I hope to update this zine when we get significantly more safe bike infrastructure in Brooklyn and laws change to make streets safer for bicyclists (and everyone) over time, but it's still important to note that each release will reflect a specific snapshot in time of bicycling in Brooklyn. All text and illustrations in the zine are my own. Thank you to Matt Denys, Geoffrey Thomas, Alex Morano, Saskia Haegens, Vishnu Reddy, Ben Turndorf, Thomas Nayem-Huzij, and Ryan Christman for suggestions for content and help with proofreading. This zine is licensed under the Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License, so you can copy and distribute this zine for noncommercial purposes in unadapted form as long as you give credit to me. Check out the Bike Brooklyn! zine on the web or download pdfs to read digitally or print here!