<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Rebase Capital</title>
  <subtitle>Write-ups of the work behind our products.</subtitle>
  <link rel="self" type="application/atom+xml" href="https://rebase.capital/feed.xml"/>
  <link rel="alternate" type="text/html" href="https://rebase.capital/blog/"/>
  <id>https://rebase.capital/</id>
  <updated>2026-09-10T00:00:00Z</updated>
  <author>
    <name>Edouard Brière</name>
    <uri>https://rebase.capital/about/</uri>
  </author>

  <entry>
    <title>2024–2026: Starting again</title>
    <link rel="alternate" type="text/html" href="https://rebase.capital/blog/2024-2026-starting-again/"/>
    <id>https://rebase.capital/blog/act-3-the-settlement/</id>
    <published>2026-09-10T00:00:00Z</published>
    <updated>2026-09-10T00:00:00Z</updated>
    <summary>Writing a specification against everything the first eighteen years cost, building a second company on the one channel that cannot be outbid, and the honest accounting of what actually decided the old defeat.</summary>
    <content type="html"><![CDATA[<p>
            The specification wasn&rsquo;t written about any market in particular. Every clause
            was the negation of something that had cost me.
          </p>
          <p>
            Then a friend showed me his inbox.
          </p>
          <p>
            Mike runs a fresh produce import business. His operational life, it turned out, looked
            like mine in 2007 — not metaphorically, <em>literally</em> the same shape: critical
            information trapped in email attachments, retyped by hand into systems, by people
            whose actual job was something else. Bills of lading, phytosanitary certificates,
            packing lists, arriving as PDFs from shipping lines and exporters, transcribed into
            the ERP, error by patient error, while containers of perishable fruit crossed oceans
            on deadlines measured in shelf-life. The spreadsheet-emailing of 2007, wearing a
            hi-vis vest.
          </p>
          <p>
            And the specification matched. Fresh produce importers don&rsquo;t google for
            software; they buy from people they trust, at trade shows, on the recommendation of
            someone they&rsquo;ve traded with for twenty years. There is no keyword auction to be
            outbid in, because there is no auction. Deep ERP integrations are the natural shape of
            the product, and switching costs the natural consequence of doing the job well. And at
            the center sits the exact technology that deflated translation — document AI — except
            here it <em>creates</em> the value: machines reading the paperwork that humans were
            wasting their days retyping.
          </p>
          <p>
            I should be accurate about the competition, because &ldquo;nobody is looking at
            this&rdquo; would be false and easy to check. Document AI for supply chains is a busy,
            well-funded space. Customs and freight document automation has taken serious venture
            money, several companies are doing it well, and the large logistics platforms are
            adding it to what they already sell. What is different about my corner is the
            customer: small and mid-sized fresh produce importers, companies of dozens rather than
            thousands, running specific ERPs, on perishable-goods timelines where a document
            arriving late has a cost measured in spoiled fruit. That is too small a wedge for
            anyone who needs six-figure contracts to make the model work, and too particular to
            serve with a general document pipeline. The moat isn&rsquo;t that the space is empty.
            It&rsquo;s that this part of it is unglamorous, sold through trade halls rather than
            demos, and takes more integration depth than a funded roadmap wants to spend.
          </p>
          <p>
            I started building in January 2026. The stack, you will be unsurprised to learn, was
            Rails — the same instrument, twentieth year of practice. I called it <a
            href="https://trackberry.com" target="_blank" rel="noopener">Trackberry</a>.
          </p>
          <h2>What eighteen years bought</h2>
          <p>
            Building the second company revealed what the first one had actually been for.
          </p>
          <p>
            The speed came from WTI. A working product in weeks, not quarters, because every
            architectural decision had been rehearsed for eighteen years — including background
            jobs for the heavy document processing, the same unglamorous plumbing that beat the
            incumbent in 2008, still working in 2026. The file-handler months turned out to be a
            transferable discipline: parsing the world&rsquo;s messy, undocumented, lying file
            formats is the same job whether the file is an Android XML or a scanned packing list
            from Peru — you sit with the real files until the edge cases surrender.
          </p>
          <p>
            The market judgment came from the scar tissue. I priced from day one. I charged for
            integrations. I kept costs near zero — the entire company runs on less than what I
            once paid <em>monthly</em> to defend my own brand name. And when the first prospects
            went quiet for two months, I did not conclude the product was wrong, because I had
            finally learned to tell the difference between a broken product and a market that
            simply buys slowly. In translation, slow buying would have meant death by funded
            competitor. In fresh produce, it means the moat is real: any market this hard to enter
            is this hard to leave.
          </p>
          <p>
            Even the distribution is the mirror image. WTI&rsquo;s customers arrived through
            search results I eventually couldn&rsquo;t afford to stand in. Trackberry&rsquo;s
            arrive through a freight forwarder who was impressed by what I&rsquo;d built, through
            an ERP integrator who trusts me because I shipped what I said I&rsquo;d ship, through
            a trade journalist, through a hall in Madrid every October. There&rsquo;s a private
            irony in that. The only competitor email I ever answered in the old days was the one
            that arrived carrying a customer&rsquo;s word-of-mouth about the man who sent it. It
            took me until my forties to notice that if that was the only door into <em>me</em>, it
            was probably the only real door into everyone.
          </p>
          <p>
            I still build alone, happily, and picking up the phone still costs me more than
            writing a thousand lines of code. What changed is scaffolding: pilot frameworks,
            follow-up rules, pre-booked meetings, every prospect interaction ending with a date.
            Mechanics where charisma should be.
          </p>
          <h2>One knock per gate</h2>
          <p>
            For years I told the story of the old defeat wrong — first as &ldquo;they
            cheated,&rdquo; later as &ldquo;the game was rigged.&rdquo; Both contain truth.
            Neither is the verdict.
          </p>
          <p>
            The rigging was real: auctions priced by other people&rsquo;s investors, search
            results owned by compounding content budgets, network effects that sent every
            open-source project to wherever everyone already was. I tried the fair channels,
            mostly once each — the ads that worked and couldn&rsquo;t be affordably scaled, a
            conference application that was refused, a free open-source tier that couldn&rsquo;t
            move the network, an MIT-licensed CLI that bought no halo. All true. And when five
            different channels fail for one operator over one decade, the common variable stops
            being the channels.
          </p>
          <p>
            Here is what I actually did at each gate. The product got eighteen years of daily
            iteration; the file handlers alone got months of grinding until every edge case
            surrendered. Each distribution channel got one knock. When the knock went unanswered,
            I accepted the verdict instantly and went back to code — where verdicts could be
            appealed with effort, where effort reliably paid, where I was safe. Look at the design
            of those experiments: minimum exposure, single attempt, immediate acceptance of
            failure, return to comfort. That is not a growth strategy that happened to fail. That
            is a shy man&rsquo;s experiment design, built — I genuinely believe unconsciously — to
            <em>confirm</em> that the uncomfortable work didn&rsquo;t pay, so the comfortable work
            could continue with a clear conscience. I A/B-tested my parsers relentlessly for
            eighteen years and never once iterated a growth channel.
          </p>
          <p>
            Beneath the choices sat a bigger one, remade annually without ever being examined: I
            stayed solo. A solo operator spending every hour on product and support has
            structurally zero hours for the slow, compounding channel work that growth requires —
            so staying solo <em>was</em> the decision not to grow, renewed every year for fifteen
            years. And the enabler deserves naming: the business was too successful to force me.
            The comfortable game paid well enough, for fifteen consecutive years, to fund avoiding
            the uncomfortable one. Broke founders learn sales in year two or die. I never had to,
            and so I never did. I avoided sales for fifteen years, and it cost me the decade.
          </p>
          <p>
            So: was I cheated? Some tried. Was the game rigged? Substantially. Did either of those
            decide my decade? No. What decided it was one knock per gate, an empty chair I
            declined to fill, and a life comfortable enough that nothing ever made me knock twice.
          </p>
          <h2>Where things stand</h2>
          <p>
            The memoir format tempts a founder to narrate victory before it happens, so here is
            where things actually stand. Trackberry, as I write this, is not yet a success. It is
            a strong start: an excellent paying client, a shipped ERP integration, a real
            pipeline, a trade show in October where the next chapter gets decided. The &ldquo;two
            successful companies&rdquo; sentence gets earned somewhere around client five.
            I&rsquo;ve stopped predicting.
          </p>
          <p>
            WebTranslateIt, meanwhile, settled into something better than the cash cow I once
            resigned it to. Over eighteen years it has grossed more than €3.5 million, and it is
            still gliding gently — but in 2026 I gave it a full redesign and a set of AI features,
            not to re-enter the growth fight, but because a product I&rsquo;d stopped resenting
            turned out to be a product I could enjoy improving again. Several of the funded
            competitors ended up consolidated into private-equity rollups and rebranded around the
            AI that shrank the category, their boom-year valuations quietly underwater. The
            fairest player of my cohort — a bootstrapper who found distribution nobody was
            contesting and built it into the product itself — is thriving, and deserves it.
          </p>
          <p>
            One more thing has started happening, and I&rsquo;ll report it flatly, because it is
            too early to mean much. Private equity does a predictable thing to the software it
            harvests: prices rise, support thins, roadmaps freeze. I wasn&rsquo;t planning a
            comeback — I was keeping the lights on and the door unlocked. Lately a few customers
            of the consolidated competitors have come through that door with migration questions.
            It is a trickle, not a flood, and WTI&rsquo;s category is still deflating under
            everyone. But the shape of it is worth writing down: the rollups&rsquo; pricing is
            quietly sending some customers back to the product that was supposed to have been made
            obsolete.
          </p>
          <h2>What it was for</h2>
          <p>
            If you&rsquo;re a bootstrapper somewhere in your own second act — outbid on your own
            name, out-shouted by content farms, watching effort and outcome come apart and
            concluding the broken variable is you — this piece exists for the sentence I needed in
            2019 and didn&rsquo;t have: <em>the game can be unwinnable while you are playing it
            perfectly.</em> And for the harder one: <em>check how many times you actually
            knocked.</em> Merit didn&rsquo;t die when the money arrived; it moved — out of the
            auctions and the search results, into trust, domain depth, integration work, the
            boring verticals.
          </p>
          <p>
            The next chapter gets decided next month, in a hall in Madrid, at the trade show where
            fresh produce importers buy from the people they trust. I&rsquo;ll be there, doing the
            thing I spent a career hiding from.
          </p>
          <p class="colophon">
            <em>M&aacute;laga, 10 September 2026.</em>
          </p>]]></content>
  </entry>

  <entry>
    <title>2012–2024: When the money arrived</title>
    <link rel="alternate" type="text/html" href="https://rebase.capital/blog/2012-2024-when-the-money-arrived/"/>
    <id>https://rebase.capital/blog/act-2-the-capital-war/</id>
    <published>2026-08-20T00:00:00Z</published>
    <updated>2026-08-20T00:00:00Z</updated>
    <summary>What happened when the money arrived: paying Google for the right to be found by people already searching for my own product, competing against balance sheets instead of products, and the year I stopped fighting for growth.</summary>
    <content type="html"><![CDATA[<p>
            At some point in the late 2010s, a new line item appeared in my monthly costs: money
            paid to Google so that people searching for the name of my own product would find my
            product. It started small. By 2023 it had peaked at €500 a month.
          </p>
          <p>
            I want to make sure the mechanics of this land, because it sounds too absurd to be
            literal. Competitors had begun bidding on the keyword &ldquo;webtranslateit.&rdquo;
            Nobody typing that word into a search box was an undecided buyer weighing options.
            They were my customers trying to reach the login page, or someone a customer had told,
            <em>use WebTranslateIt, it&rsquo;s good.</em> The ads sat above my own result, dressed
            as answers. My choice was to outbid them on my own name or watch some percentage of
            people click the top link without reading it. So I paid — an escalating monthly fee,
            for years, for the right to be found by people who were already looking for me. The
            bidding on my name grew fiercest not in the boom, but in 2023, when the category
            itself had started to shrink.
          </p>
          <p>
            Google, of course, collected from both sides. The competitor paid to ambush; I paid to
            defend; the auction house took every check. I eventually looked into owning my name in
            the one place I could — the trademark registers — and got a lesson in how even that is
            priced. €200 for France, ten years. Each additional territory, €200 to €1,000.
            Worldwide protection: roughly twenty thousand euros, which I could not afford. So I
            chose three territories and left the rest of the planet legally open. Keeping the name
            I had built was not a right. It was a subscription.
          </p>
          <h2>The money arrives</h2>
          <p>
            It didn&rsquo;t happen in one day. Around 2012 — the same year GitHub, my existence
            proof, took its first venture round — capital discovered localization. The logic was
            sound, from capital&rsquo;s point of view: every startup was going international,
            continuous deployment had made spreadsheet-emailing untenable, and a whole industry
            needed workflow software with recurring revenue. That is the kind of sentence that
            raises funds. And so it did, at company after company, in rounds that grew from
            millions to tens of millions.
          </p>
          <p>
            The tone of my inbox changed with it. In 2010, competitors wrote about craft and
            collaboration. By late 2012, a funded competitor was writing to inform me of plans to
            take 80% of the entire market on the strength of a huge new funding round. Read the
            shape of that claim slowly, because everything about the next decade is inside it. Not
            <em>we&rsquo;ve built something better</em>. Not <em>customers prefer us</em>. The
            claim was: <em>we have money, therefore we will take the market.</em> In the world of
            2010, that sentence would have been a non sequitur — funding didn&rsquo;t parse
            translation files or keep servers up. In the world it announced, it was simply an
            accurate description of the new rules.
          </p>
          <p>
            None of these companies needed to be profitable. That is not a criticism; it is a
            description of the strategy. Venture-funded SaaS in that decade was priced on growth,
            and growth could be purchased: hire content teams to carpet-bomb search results, build
            fifty integrations, hire enterprise salespeople, and buy every click in the category
            at a loss, because the loss was the investors&rsquo; problem.
          </p>
          <p>
            Here is what that does to an auction. Google Ads doesn&rsquo;t price a keyword at what
            a customer is worth. It prices it at what the most subsidized bidder will pay. When
            your competitors&rsquo; cost of capital is a term sheet and yours is your own bank
            account, the clearing price rises past the point where a profitable business can
            participate. I ran the numbers more times than I want to admit, and they always said
            the same thing: at these prices, every customer acquired through ads would cost more
            than they&rsquo;d ever pay me. People describe this period of SaaS as competitive. It
            wasn&rsquo;t competition in any sense I&rsquo;d recognize. Before, we both shipped and
            customers judged the results. Now the contest was over which balance sheet could
            absorb losses longer, and I had entered it needing to make money.
          </p>
          <p>
            I made one strategic decision in response, early, in writing, in a family email. The
            obvious counter-move to subsidized competitors was to cut prices. I refused, and my
            reasoning, verbatim from 2012: there are two kinds of customers — those who buy on
            price, and those who buy on the quality of a product, whatever it costs. Mine were the
            second kind. The low-cost clients who found fourteen euros a month too expensive, I
            preferred to let go to the competition. It reads almost quaint now. It turned out to
            be one of the most consequential decisions of the eighteen years: it&rsquo;s why the
            customers who stayed were the ones worth keeping, why the revenue survived everything
            that followed, and why the business never entered the race to the bottom that subsidy
            always wins.
          </p>
          <h2>Winning the wrong game</h2>
          <p>
            The strange part — the part that took me years to see clearly — is that through all of
            this, I was still winning the old game. The product held up. Customers who left for a
            shinier funded competitor had a habit of coming back after the first serious import
            job or the first support ticket that went unanswered for a week. Churn stayed low. By
            2021, WebTranslateIt was doing about €25,000 a month, the best it had ever done,
            without a single ad click I didn&rsquo;t overpay for.
          </p>
          <p>
            By every metric I had been raised on as a developer, this was success. And I was
            exhausted in a way I couldn&rsquo;t explain.
          </p>
          <p>
            Life, meanwhile, had not waited for the market to become fair. My daughter was born in
            2015, my son in 2019 — squarely in the middle of these years, so that all of it was
            happening to a man who was also becoming a father twice over. The business was the
            only income under a family of four.
          </p>
          <p>
            I understand the exhaustion better now. Peak revenue meant peak everything: every sale
            was also me doing the onboarding, the support, the roadmap that competitors with forty
            employees were mining for ideas. But underneath the workload was something more
            corrosive: the growing knowledge that effort and outcome had come apart. Early on,
            working harder made the product better and the better product won. By the late 2010s,
            I could work as hard as I wanted — the channels were owned, the auctions were priced
            by other people&rsquo;s investors, and the category&rsquo;s story was being written by
            whoever had the largest content budget. There is a particular kind of tiredness that
            comes from playing a game well after the game has stopped mattering. I had it for
            years before I could name it.
          </p>
          <p>
            Two exits had presented themselves along the way — the customer&rsquo;s offer in 2010,
            and in early 2012 a call with the best-funded company in my category, whose CEO a
            customer of mine had vouched for, and where the opportunity on the table turned out to
            be an acquihire: fold the product, join the winner, take the badge. He was pleasant,
            exactly as advertised, and then, in the least dramatic ending imaginable, neither of
            us followed through. (Of all the emails competitors ever sent me, the one I answered
            was the one that arrived carrying a trusted person&rsquo;s word-of-mouth.) I stayed
            where I was, for reasons that felt obvious at the time and got harder to reconstruct
            as the decade wore on: the product was mine, the revenue was real, and I had won every
            contest I could see. At the peak, keeping WTI looked shrewd. Around 2021, drained and
            boxed in, it looked like vanity.
          </p>
          <h2>Force majeure</h2>
          <p>
            On a morning in late February 2022, about a thousand euros of my monthly revenue
            ceased to exist. Nobody churned. Nobody was unhappy. Russia had invaded Ukraine, the
            sanctions came down, the payment networks suspended operations, and every Russian
            software company paying for WebTranslateIt was cut off from Western payment rails
            between one billing cycle and the next. These were good customers, some subscribers
            for years. They didn&rsquo;t leave; the world&rsquo;s plumbing was shut off between
            us. There was no counter-move. Four to five percent of my revenue, deleted by
            geopolitics, in a week. And I want to be careful with proportion: I lost a line item;
            my Russian customers lost their connection to the world&rsquo;s software economy;
            Ukrainians were losing their homes and lives.
          </p>
          <p>
            Nine months later, ChatGPT launched, and the ground under the entire category began to
            move. Translation management systems existed to orchestrate an expensive, scarce
            resource: human translators. Then a general-purpose AI started producing translations
            at near-human quality for pennies, and the assumption dissolved. Not the whole product
            — software still needs string management, versioning, context, deploy integration —
            but the <em>spend</em> flowing through the category began to deflate. The funded
            competitors saw it too: their marketing pivoted almost overnight from &ldquo;manage
            your translators&rdquo; to &ldquo;govern your AI,&rdquo; now selling the cost collapse
            itself.
          </p>
          <p>
            And 2023 — the year the pie visibly began to shrink — is the year I chose to push for
            growth. I had never really stopped believing the old rules deep down: work harder,
            build better, and it comes back to you. I hired help — a British developer, and I
            loved how I found him: he was a WebTranslateIt user. I spent fifty thousand on him,
            and together we did something unglamorous and vital: migrated WTI across a decade of
            framework history, <a
            href="/blog/upgrading-webtranslateit-from-rails-3-2-to-rails-7/">from Rails 3 to Rails
            7</a>. A sixteen-year-old codebase came out the other side modern, securable,
            maintainable. That was the part of the plan that worked.
          </p>
          <p>
            The growth part hit the wall at full speed. The auctions were more impossible than
            ever — this was the year the bidding on my own name peaked. A decade of venture-funded
            content teams owned every search result that mattered. And beneath both, the AI
            deflation meant I was trying to grow into a market that was contracting. I ran
            campaign after campaign into that configuration. Nothing converted, and every flat
            month read, from the inside, not as <em>the structure is unwinnable</em> but as <em>I
            am failing.</em> Structural walls are invisible from inside. You cannot see the
            subsidy behind the auction price or the decade behind the search ranking; you can only
            see your own effort going in and nothing coming out. And a builder who has spent his
            whole life on the equation <em>effort makes things better</em> will conclude, wrongly,
            that the broken variable is himself.
          </p>
          <p>
            It cost me at home, too, more than I&rsquo;ll detail here. My wife was working on
            WebTranslateIt with me then — marketing, accounting — which meant the stalling numbers
            weren&rsquo;t something I could leave at the office; they sat down to dinner with us.
            We were two people absorbing a market failure as if it were each other&rsquo;s. We
            came through it, and part of how we came through it is the rest of this story. But
            2023 asked a price from the person standing closest to me, and I want that on the
            record.
          </p>
          <h2>Fuck it</h2>
          <p>
            The turn, when it came, didn&rsquo;t feel like wisdom. It felt like profanity. At some
            point in 2023 I looked at the whole board at once — the ransom on my own name, the
            auctions priced by other people&rsquo;s investors, the category deflating under
            everyone&rsquo;s feet, the campaigns converting nothing, the tension at home — and
            something in me said, with great clarity and no elegance: <em>fuck it.</em>
          </p>
          <p>
            Fuck the growth fight. Not the product — the product was good, newly modernized, loved
            by the customers who had it. But the fight for new customers was being fought with
            weapons I would never own, over territory that was shrinking anyway, at a price being
            paid by my health and my marriage. I stopped bidding. I stopped campaigning.
          </p>
          <p>
            It wasn&rsquo;t surrender — nobody took anything. The customers stayed, because the
            file handlers still worked and the support emails still got answered fast. The revenue
            stayed, easing rather than collapsing. What I gave up was the fight for growth, which
            I can now say with the confidence of hindsight and arithmetic was unwinnable at any
            level of effort, by anyone in my position, in that year. What I kept was a profitable
            product, a modernized codebase, eighteen years of hard-won judgment, a repaired
            marriage, and — for the first time in years — attention.
          </p>
          <p>
            The first place I pointed that attention was not at a business. It was at myself.
            Somewhere in those years I had stopped being a person with a body and become a support
            queue with legs, and the withdrawal made room to reverse that: a coach once a week,
            training three times a week; fast hikes in the mountains above Málaga; sleep treated
            as infrastructure instead of leftover. The energy that built everything that came
            after was manufactured in those months. I got so far into it that for a while I
            seriously considered making fitness YouTube videos my next act. I&rsquo;m glad I
            didn&rsquo;t — the world needed another mid-forties European explaining protein timing
            like it needed another translation management system — but I note it because it shows
            how genuinely open the question was.
          </p>
          <p>
            When the search sobered up, I pointed it at a question I hadn&rsquo;t seriously asked
            since 2008: <em>if I were choosing a market today, knowing everything the last decade
            taught me — what would it need to look like?</em> The answer was very specific. No ad
            auctions, because auctions are won by subsidy. No search-ranked distribution, because
            content compounds for the funded. A market that buys on trust and relationships,
            because trust cannot be outbid. Deep integrations and switching costs, because easy-in
            had proven to mean easy-out. Boring, unsexy, invisible to venture capital. And
            ideally, powered by the very technology that had deflated my first category — because
            if AI was going to dissolve markets, I wanted to be on the side of it, in a place
            where it created value instead of destroying mine.
          </p>
          <p>
            I did not know it yet, but I had just written the specification for a container full
            of blueberries.
          </p>
          <p class="colophon">
            <em>Blackheath, London, 20 August 2026.</em>
          </p>]]></content>
  </entry>

  <entry>
    <title>2007–2012: Building it</title>
    <link rel="alternate" type="text/html" href="https://rebase.capital/blog/2007-2012-building-it/"/>
    <id>https://rebase.capital/blog/act-1-the-technical-war/</id>
    <published>2026-07-25T00:00:00Z</published>
    <updated>2026-07-25T00:00:00Z</updated>
    <summary>The first of three pieces about eighteen years of WebTranslateIt — what it taught me about products, markets, and why I built my second company as the structural opposite of my first.</summary>
    <content type="html"><![CDATA[<p>
            <a href="https://webtranslateit.com" target="_blank"
            rel="noopener">WebTranslateIt</a>&rsquo;s first commit is dated October 4, 2008, and
            it was made from Sardinia, where I was on holiday. Picture that honestly: three weeks
            after Lehman Brothers collapsed, with the world&rsquo;s financial system on fire, a
            French developer on an Italian beach holiday opens his laptop and creates a Subversion
            repository for a translation tool — because the idea wouldn&rsquo;t leave him alone
            even there. (Yes, <a href="https://subversion.apache.org" target="_blank"
            rel="noopener">Subversion</a>. It was October 2008; <a href="https://github.com"
            target="_blank" rel="noopener">GitHub</a> was six months old and git was still
            something you apologized for suggesting.)
          </p>
          <p>
            I can&rsquo;t claim the timing was strategy. But it shaped everything about these
            years: the capital that would later transform my industry was, in October 2008, busy
            not existing. The field was empty of everyone except people who simply wanted to
            build.
          </p>
          <p>
            The idea was born inside <a href="https://www.last.fm" target="_blank"
            rel="noopener">Last.fm</a>, where I worked in the late 2000s. In 2006–2007 I built an
            internal tool there to manage the site&rsquo;s translations, because the way software
            got translated everywhere was this: someone exported the strings into a spreadsheet,
            emailed it to translators, waited, received several slightly different spreadsheets
            back, and merged them by hand. Then a developer changed twelve strings, and the whole
            thing started again. Nobody called this a workflow. It was just what everyone did.
          </p>
          <p>
            The internal tool proved the idea worked. But WebTranslateIt itself shares not a
            single line of code with it — I wrote WTI from scratch, as its own thing, from Sweden,
            where I was working remotely for Last.fm years before remote work was a thing anyone
            did on purpose.
          </p>
          <p>
            Fourteen months passed between that first commit and the first euro of revenue, in
            December 2009. Fourteen months of nights and weekends on a bet nobody was validating —
            no users cheering, no investors pattern-matching, no Product Hunt. Founder stories
            tend to edit this part out because nothing happens in it that can be narrated. But
            it&rsquo;s the part that decides everything: the toll booth existed for more than a
            year before the road did.
          </p>
          <h2>The incumbent that couldn&rsquo;t scale</h2>
          <p>
            An incumbent already existed — 99translations.com — and I want to say clearly: it was
            good. The idea was right, the interface made sense, someone had genuinely thought
            about the problem. But it had been built the way most web apps were built in those
            years, with everything happening in the request. You uploaded a language file, and the
            server parsed it, diffed it, and updated the database while your browser waited and
            the rest of the site queued up behind you. That&rsquo;s fine for a demo. It&rsquo;s
            fatal for the actual workload, because translation files are the definition of lumpy
            traffic: nothing for days, then a customer imports forty locale files at once. Every
            serious customer was a denial-of-service attack on themselves.
          </p>
          <p>
            My one structural insight — and in 2007 it counted as an insight — was that all of the
            heavy work belonged in background jobs. Accept the file, queue the work, keep the site
            fast for everyone else. Today a junior developer does this by reflex; in 2008, on
            Rails 1.x, before the job libraries we now take for granted, it meant assembling the
            machinery yourself. It was unglamorous plumbing. It was also a moat: WebTranslateIt
            could take whatever a real customer threw at it, and it stayed up. The early contest
            in translation management software wasn&rsquo;t over features or price. It was over
            architecture, and architecture was something one developer could win.
          </p>
          <p>
            The second moat was less visible and took far longer: the file handlers. A translation
            platform lives or dies on the formats it understands — Rails YAML, gettext PO, iOS
            strings, Android XML, and a long tail of dialects, each with its own escaping rules,
            its own plural forms, its own undocumented quirks that only surface when a real
            customer uploads a real file. I spent months on this — months of the least glamorous
            programming there is, reverse-engineering how each ecosystem actually serialized its
            strings versus how its documentation claimed it did. That file-handling code is still
            in production today. Frameworks rose and fell, competitors raised and burned nine
            figures, and the parsers I wrote in a flat in Sweden keep parsing.
          </p>
          <h2>The reference implementation</h2>
          <p>
            Through the years that followed, something happened that I only understood much later:
            the product stopped being just a product and became the spec.
          </p>
          <p>
            Competitors arrived, some from the open-source world, some funded, some as teams of
            twenty against my team of one. And the twenty were, in at least one case I could
            verify, reading the one&rsquo;s documentation to figure out what to build: tickets in
            a competitor&rsquo;s public issue tracker linked to <em>my documentation</em> — not to
            standards, not to academic papers, to the WebTranslateIt docs, as the description of
            how the feature should work. I was annoyed for about a day. Then I understood what I
            was looking at. When your competitor&rsquo;s engineering tickets cite your
            documentation as the requirement, you have already won the argument about what the
            product should be. Being copied is what winning that argument looks like from the
            inside. It just doesn&rsquo;t pay royalties. One competitor later shipped a
            command-line tool that mirrored mine down to the verbs — same commands, same grammar,
            same shape of output.
          </p>
          <p>
            In a contest decided by architecture and product judgment, one developer can keep a
            funded team on its toes indefinitely. That stopped being the contest.
          </p>
          <h2>Where things stood in 2012</h2>
          <p>
            By 2012 the scoreboard, as I understood it, read well. The architecture held.
            Customers who tried competitors came back after the first big import choked. Revenue
            was real and growing, and I was doing all of it — code, support, invoices — from my
            own two hands, with no investors and no debt.
          </p>
          <p>
            Even advertising worked, in that innocent way that&rsquo;s hard to describe to anyone
            who entered SaaS after 2015. At one point I spent about $700 on ads, and it brought a
            wave of new customers — actual, paying, staying customers, acquired for the price of a
            laptop. Clicks were cheap because the only people bidding were people who, like me,
            needed the math to work. Remember that $700, because a decade later I would be paying
            almost that much <em>every month</em> for ads that acquired nobody at all.
          </p>
          <p>
            The era had its absurdities too. On June 21, 2011 — the day after my 29th birthday — I
            was woken at 7:11 in the morning by monitoring alerts: the server was unreachable by
            any means. The hosting company first blamed a router bug. Then I noticed that <a
            href="https://pinboard.in" target="_blank" rel="noopener">Pinboard</a> and <a
            href="https://www.instapaper.com" target="_blank" rel="noopener">Instapaper</a> —
            hosted at the same ISP, because in 2011 the entire indie web apparently shared the
            same racks in Virginia — were down too. The truth came out over the day: the FBI had
            raided the datacenter in pursuit of someone else entirely and pulled three racks of
            servers. Some machines were carried away as evidence; mine was merely disconnected,
            collateral to my rack-neighbors&rsquo; misfortune. I spent the morning tweeting
            updates, and by 10:30 the site was back with no data lost. I published a post-mortem
            and apologized to my customers for the FBI.
          </p>
          <p>
            There&rsquo;s a lunch from 2010 that captures the era for me. I sat down with Tom
            Preston-Werner and Kyle Neath of GitHub — then still a young company, years away from
            taking its first venture round. We were running the same stack: Ruby, Rails, the same
            gems, probably the same deployment headaches. GitHub was proof of the thesis I was
            betting my working life on — that a small team of developers, with no permission and
            no capital, could build something the whole industry adopted purely because it was
            better. What strikes me in hindsight isn&rsquo;t anything said at the table.
            It&rsquo;s that the table existed at all. The industry was still that size.
          </p>
          <p>
            That same year, the CEO of a company that was one of my happiest customers wrote to
            offer something remarkable: an investment or an acquisition. His company was
            self-funded, three owners, a hobby turned business. They had localized their whole
            platform on WTI, and his reasoning was the era in miniature — they had, he wrote, seen
            many useful small vendors come and go over the years, and they didn&rsquo;t want that
            to happen to this one. I said no, almost without deliberating — why would I sell the
            thing that was working, in a world where the rules were fair and I was winning under
            them? It was the most reasonable decision in the world, given everything I could see
            in 2010. His fear — that WTI would come and go — is the one prediction about my
            product that never came true. Sixteen years later, it&rsquo;s still running, still
            independent, still answering support email from the same man.
          </p>
          <h2>The confession</h2>
          <p>
            Before the money arrived, one thing about the man who was winning.
          </p>
          <p>
            Around that time, the founder of a competing product wrote me the friendliest email a
            rival would ever send: praising the craft in WebTranslateIt, proposing that our tools
            might talk to each other, floating collaboration with no specific agenda, closing with
            an invitation to meet at an open-source conference — with a smiley. That was simply
            how the neighborhood talked in 2010.
          </p>
          <p>
            I never replied. And the honest reason is less flattering than shyness. I heard the
            praise as something slightly patronizing — the famous project patting the indie
            craftsman on the head — and my private response was pure pride: I thought I had the
            superior product, plainly, and that this settled the matter. What did they have that I
            wanted? Fame, I told myself dismissively. Community. Interesting customers. In other
            words — and I could not see this for another thirteen years — they had
            <em>distribution</em>, the exact thing whose absence would eventually cap everything I
            built, offered to me in embryo, wrapped in a compliment. I scored the game on product
            quality, and by my scoring I was winning. They scored it on reach.
          </p>
          <p>
            I had a creed for all this, and it had a patron saint: Steve Jobs, then at the height
            of his myth. What I took from him — what my whole generation of builders took from him
            — was the excellence half: obsess over the craft, say no to almost everything, let the
            product be the entire argument. It didn&rsquo;t occur to me until embarrassingly
            recently that the actual Jobs was also the greatest salesman, negotiator, and
            distribution strategist of his era. We absorbed his editing and never noticed his
            selling.
          </p>
          <p>
            But writing this forced me one layer deeper. The pride wasn&rsquo;t really the
            foundation. The foundation was that I was shy. I didn&rsquo;t know how to have that
            phone call, how to work a conference hallway, how to reply to a warm email from a
            stranger without it costing me something I couldn&rsquo;t name. And a shy craftsman
            who finds a philosophy in which the craft is everything and the humans are
            interruption has not found a philosophy — he has found armor. When the business needed
            me to pick up the phone, go to the fair, chase the partnership — the hard, exposed,
            unscorable things — there was always, conveniently, code to write instead. I hid in
            the open, shipping, for years, and called it focus.
          </p>
          <p>
            Almost three years after that unanswered email, another one arrived — from a
            competitor that had just closed a huge funding round, informing me of its plans to
            take 80% of the entire market. I didn&rsquo;t answer that one either. But it marked
            the end of one era and the start of another.
          </p>
          <p class="colophon">
            <em>D&uacute;n Laoghaire, 25 July 2026.</em>
          </p>]]></content>
  </entry>

  <entry>
    <title>Upgrading WebTranslateIt from Rails 3.2 to Rails 7</title>
    <link rel="alternate" type="text/html" href="https://rebase.capital/blog/upgrading-webtranslateit-from-rails-3-2-to-rails-7/"/>
    <id>https://rebase.capital/blog/upgrading-webtranslateit-from-rails-3-2-to-rails-7/</id>
    <published>2022-10-16T00:00:00Z</published>
    <updated>2022-10-16T00:00:00Z</updated>
    <summary>How a team of two took a large Rails app from Rails 3.2 and Ruby 2.7 to Rails 7 and Ruby 3.1 in four months.</summary>
    <content type="html"><![CDATA[<p>
            About a year ago, WebTranslateIt ran on Rails 3.2 LTS and Ruby 2.7. It now runs on vanilla
            Rails 7 and Ruby 3.1. The app started life in 2008 as a Rails 2 app. Time flies.
          </p>
          <p>
            <a href="https://webtranslateit.com" target="_blank" rel="noopener">WebTranslateIt</a> is a
            Rails app with a large codebase, serving about 35 requests per second on average.
          </p>
          <p>
            Rails LTS is a maintained fork of Rails sold by Makandra, with continuous security fixes.
            They also ship patched versions of some Rails dependencies, rake among them. It let us stay
            on an old version of Rails indefinitely and safely, but staying was never the plan. We
            wanted the newer features and the performance improvements. We recommend Rails LTS all the
            same.
          </p>
          <p>
            First, why we were running something so old. For years, WebTranslateIt had a development
            team of one: me. I tried on and off for two years to get from Rails 3.2 to Rails 4, and it
            was simply too hard. Running a business meant shipping the features that paid for it, so
            the upgrade kept getting postponed.
          </p>
          <p>
            We are two now. James, a freelance Rails developer, took the project on. He is experienced
            and knows the framework deeply, and that is why we moved as fast as we did. Here is how we
            went from Rails 3.2 to 7.0, and Ruby 2.7 to 3.1, in four months.
          </p>

          <h2>Preparation</h2>
          <p>
            We started by improving test coverage. Upgrading across a gap that size without good
            coverage is asking for trouble. We spent a few months writing unit tests over the important
            parts of the code, plus feature tests with Capybara.
          </p>
          <p>
            We added RuboCop and fixed the offenses. Normalizing the code and catching problems early,
            many of them correctable automatically, helped enormously. We shipped all of it before
            touching Rails.
          </p>
          <p>
            Strong parameters was one of the headline Rails 4 features, so we added the
            strong_parameters gem on Rails 3 and made the app ready ahead of time.
          </p>
          <p>
            Before each upgrade we read the Rails upgrade guide and the upgrade notes on fastruby.io.
            Both were a great help.
          </p>

          <h2>Rails 4</h2>
          <p>
            Rails 4 was the hardest of the upgrades, despite everything we had done in advance. A lot
            changed in the framework. Rather than recount all of it, here are three things worth
            knowing if you are facing the same jump.
          </p>

          <h3>Go from latest to latest</h3>
          <p>
            We started by moving from Rails 3.2 LTS to vanilla 4.0, and hit a wall. Rails 3.2 LTS let
            us run Ruby 2.7; vanilla 4.0 did not, so we had to downgrade every dependency to a version
            old enough to match. Many of those older versions had different public APIs, which meant
            reimplementing our own code against them. Dependency hell.
          </p>
          <p>
            Then, having finished, we could not release it. Vanilla 4.0 carries known security issues,
            so shipping it would have been a step backwards.
          </p>
          <p>
            So we carried on to vanilla 4.1, then 4.2, then 4.2 LTS. Rails 4.2 LTS supports Ruby 2.7,
            so we could finally upgrade all those dependencies again, and undo the API changes we had
            just made.
          </p>
          <p>
            It was a lot of wasted work. In hindsight, and contrary to what the Rails upgrade guide
            advises, we should have gone straight from 3.2 LTS to 4.2 LTS and skipped the detour
            entirely. We learned the lesson and did exactly that for every later version, and it went
            much faster.
          </p>

          <h3>Backport what you can</h3>
          <p>
            We made one commit for every small change needed to run on the next version of Rails.
            Plenty of those changes work fine on the current version too.
          </p>
          <p>
            Whenever that was the case, we cherry-picked the backportable commits into a pull request
            against main, checked everything still worked, and deployed it. Then we rebased main onto
            the Rails 4 branch. The goal was to keep the Rails 4 pull request as small as possible.
          </p>

          <h3>Have a way back</h3>
          <p>
            We also made sure the upgraded app was easy to revert. When a release was ready, we tested
            the water by deploying the branch without merging it:
          </p>
          <pre>cap production deploy BRANCH=rails4</pre>
          <p>and going back to Rails 3 was one command:</p>
          <pre>cap production deploy</pre>
          <p>
            We deployed to staging first, every time. A small changeset plus a one-command rollback is
            what let us deploy with confidence.
          </p>
          <p>
            Rails 4 went out on May 4. Two months from Rails 3.2 to 4.2, with no disruption.
          </p>

          <h2>Rails 5</h2>
          <p>
            James started on Rails 5 the day Rails 4 shipped, this time targeting the LTS release,
            which made it much easier.
          </p>
          <p>Meanwhile I had maintenance to do:</p>
          <ul>
            <li>read the logs for deprecation warnings and fix them</li>
            <li>
              let Dependabot upgrade our dependencies. There was a lot to get through, since many gems
              had dropped Rails 3 support. We rebased them onto main one at a time and released them
              gradually.
            </li>
            <li>point RuboCop at Rails 4 and work through the new offenses, again in small releases.</li>
          </ul>
          <p>
            All of it was rebased onto the Rails 5 branch, which helped that upgrade along. Team work.
          </p>
          <p>
            Rails 5 went out on June 5, almost exactly a month after Rails 4.
          </p>

          <h2>Serialization</h2>
          <p>
            Rails 5 added support for Postgres JSONB columns, so we converted every field that had been
            serialized as YAML since Rails 2. Plural forms on translations were one of them. Migrating
            30 million translations took a week, and we found a way to do it without any disruption.
            That deserves a post of its own.
          </p>

          <h2>Rails 6</h2>
          <p>
            We went straight on to Rails 6. After 3 to 4 and 4 to 5, this was a small gap. Rails 6.1 was
            still supported at the time, so we went to vanilla 6.1. It felt good to be back among
            supported releases.
          </p>
          <p>
            Rails 6 went out on June 13, twelve days after Rails 5. It went that fast because by then we
            were practiced at this, and RuboCop had kept the code in good shape. There was not much to
            change.
          </p>
          <p>
            Rails 6 introduced framework defaults, so we spent the next few days turning them on one at
            a time and releasing each one. As usual, we watched for deprecation warnings and let
            Dependabot do its work.
          </p>

          <h2>Ruby 3.0, then 3.1</h2>
          <p>
            Rails 6 supports Ruby 3.0, so we upgraded and released on June 14, the day after Rails 6.
          </p>
          <p>
            Then we tried Ruby 3.1 on Rails 6.1, and it worked. We upgraded on June 23, with no changes
            at all.
          </p>

          <h2>Rails 7</h2>
          <p>
            I had not even released Rails 6 when James asked on Slack: &ldquo;Guess how many failing
            specs we have on Rails 7?&rdquo; He was about to go on holiday and wanted the upgrade
            finished. We had one failing spec. The Rails 7 release was ready before Rails 6 had shipped.
          </p>
          <p>
            Rails 7 went out on June 28. We spent the following days enabling the new defaults one by
            one, clearing deprecation warnings and fixing RuboCop offenses.
          </p>

          <h2>What we learned</h2>
          <p>
            Rails 3.2 to Rails 7 in about four months, with a team of two. I will not pretend it was
            relaxing. The holiday afterwards was well earned.
          </p>
          <p>
            Rails upgrades have gotten much easier over the years. There are fewer breaking changes, and
            the framework defaults files let you turn new behavior on one piece at a time.
          </p>
          <p>
            Upgrade stories usually leave out the infrastructure work, and that was the larger part for
            us. Changing how we serialized data was a big migration in its own right, because of the
            size of the database. We also adopted a couple of abandoned gems: we now maintain version_fu
            and payday so they work on Ruby 3.1 and Rails 7.
          </p>
          <p>
            The app uses far less memory now, thanks to Ruby 3.1 and to the dependencies we could
            finally upgrade. It is faster and more reliable than it has ever been.
          </p>]]></content>
  </entry>
</feed>
