Before there was a URL
I joined Stripe in January 2019, on the Checkout team.
Stripe Checkout was the company’s "easy button" for accepting payments — a hosted form you could drop into your existing site with a few lines of JavaScript. By 2019 it was a mature product. Tens of thousands of businesses used it. The quarterly roadmap was the kind you can predict before reading: better mobile, more localization, deeper customization, faster page loads.
I remember the first user-research session that broke the roadmap.
The interview that broke the roadmap
We were running a recurring set of interviews with the smallest businesses on the platform — businesses with under $50K in annualized volume, often a single founder, often on the platform for less than 90 days. The recruiter had screened for merchants who had started a Checkout integration in the last 30 days. We thought we were going to get feedback on the integration experience.
Instead, three out of five sessions in a row, the merchant didn’t have a website at all.
They had a Substack. Or a Notion page. Or a Linktree. Or just an Instagram bio with a Calendly link. They’d opened a Stripe account because someone told them to. They’d looked at the integration docs, gotten lost in the JavaScript, and given up. The Checkout we shipped was for a category of merchant they were not — a category that owned a website.
The interviewer asked one of them: if there were a way to take payment without a website, would you use it?
She laughed and said: that’s literally my entire problem.
I went back to my desk. I pulled signup-funnel data. The pattern she had described wasn’t a personal anecdote. It was the dominant story in our smallest cohort. The vast majority of merchants under $50K had started a Checkout integration. The vast majority of them had never finished. They weren’t paying us anything. They were giving up.
The pitch we wrote
Three of us — a designer, an eng lead, and me — wrote a one-pager that week. The pitch was deliberately not "Checkout without JavaScript." It was: a URL that, by itself, is the payment surface. No website, no integration, no code. Paste it anywhere — iMessage, email, a tweet, the bio of an Instagram account.
We took it to our director. She read it twice and said, this is interesting. The problem is it’s also probably going to eat Checkout’s lunch.
The fight that almost killed it
The argument that followed lasted about six months.
The case against Payment Links was clean. Stripe Checkout was a working revenue stream, with engineering investment going back years. Telling our existing Checkout merchants — the ones who had integrated, who had followed the docs, who had built websites — that they could now skip all of that with a URL was, structurally, a self-cannibalization story. Why would the team that owned Checkout build the thing that made Checkout less necessary?
The case for Payment Links was harder to make and won on three points.
The first: the merchants who would adopt Payment Links were almost entirely merchants Checkout was not serving today. Not "Checkout merchants who would downgrade." A different population. Checkout’s own data showed it — the sub-$50K cohort tried Checkout, gave up, and disappeared from our funnel. Those merchants weren’t Stripe’s revenue. They were Stripe’s churn.
The second: if we didn’t ship it, someone would. Square Cash had the consumer side. PayPal.me had a version of the URL pattern that PayPal had never invested in. Wix and Squarespace were quietly making it easier to take payment without leaving their walled gardens. The question wasn’t does this category exist. It was do we own it or does someone else.
The third — the one that closed the fight — was a framing one of the senior PMs offered late in a meeting: Checkout serves merchants who have built a thing. Payment Links serves merchants who haven’t built a thing yet. They will eventually graduate from one to the other. We should make both surfaces ours.
That ended the argument. We got staffed.
The first prototype
The first version was something a designer and one engineer hacked together over an internal hackathon — a form in the dashboard where you typed a price, clicked a button, and got a URL. The URL went to a hardcoded checkout page that took the price as a query param. Held together with rubber bands.
It still made me stop when I clicked it the first time. You could text the URL to your phone, open it on mobile, type your card, get charged. No website. No code. The simplest thing in the entire Stripe catalog.
Once we knew the surface was real, the architectural questions came in fast.
Four moments in the build
The first big question was where the page lived. The intuitive answer was a customer subdomain — merchant-name.stripe.com or some custom domain — so the merchant got branded credit. The decision we landed on, after a few weeks of debate, was the opposite: every Payment Link resolves to a page on stripe.com itself. The merchant gets a URL that says stripe.com/pay/[id]. That looks worse from a branding perspective. It works far better for trust. The cardholder is typing into a domain millions already trust. The merchant inherits PCI compliance for free, never sees the card number, never carries the security weight. For a one-person operation, that’s the difference between exists and doesn’t.
Two months in, the engineer found a bug. The dashboard form let you create the same Payment Link twice if you double-clicked the button. The merchant ended up with two URLs charging the same customer twice. We fixed the dashboard. Then we asked the harder version of the question: what stops a customer from double-paying because they double-tapped on the page itself, on a flaky train Wi-Fi connection? The fix wasn’t a UI fix. It was making the payment intent a strict state machine — requires_payment_method → processing → succeeded — with transition rules that mathematically refuse a second charge once one is in flight. Idempotency keys at the API layer. Correct under failure. Not smart. Correct. Same coatcheck ticket, five times to the bouncer, one coat back.
Black Friday 2021 was our first holiday peak with Payment Links live. Volumes hit numbers the team hadn’t modeled. Twenty minutes into the spike, an internal dashboard started lagging — not the payment engine itself, just the analytics and reporting that ran alongside it. The team made a decision in real time: throttle the analytics, queue the reports, keep the payment path clean. It worked. We came out of that quarter with a principle that’s shaped every roadmap I’ve owned since: in any system that handles money, the critical path is sacred. You can defer features. You can defer reports. You cannot defer correctness.
Six months after launch, our biggest SaaS customers started asking why we weren’t recovering more failed payments. The naive retry — at midnight, every day — was costing them money. We built Smart Retries, which doesn’t retry at midnight. It retries when this card historically clears. Thursday at 3pm, when the cardholder’s payday hits the account. For a SaaS business at scale, Smart Retries recovers a meaningful percentage of failed-payment volume that would otherwise churn into involuntary cancellations. The kind of feature that doesn’t ship as a feature. It ships as money the customer didn’t lose.
The launch — and what people did with it
It went live in April 2021. Within a year, tens of thousands of merchants were on it. The interesting thing wasn’t the volume. It was the use cases we hadn’t imagined.
A digital-medical-appointments startup ran into the spam problem common to free booking flows: hundreds of fake appointments per day. Their hack: a $1 booking fee, taken via a Payment Link, refunded after the appointment. Not for the dollar. For the friction. The hand reaching for the wallet was the filter.
European utility companies — water, electric, gas — printed Payment Links as QR codes on their paper bills. Tap to pay. Customer-service call volumes dropped. The cost-savings line on the next quarter’s earnings call wasn’t modernization. It was Payment Links.
Neither use was on our launch roadmap. Neither needed our buy-in. They saw a URL that did one thing reliably and applied it to their problem.
What I took with me
Three years on Payment Links was three years inside an organization that had decided, at every level, that correctness under failure was the table stakes. Not a feature. Not a polish line. Table stakes. The interview process, internally called bug squash, was built around it. The phrase, internally, was operating well. You can’t put either in a PRD. You can put them in a hiring rubric.
The other thing I took: cannibalization fights are usually the wrong fight. The Checkout-vs-Payment-Links argument lasted six months, and it was almost always framed as zero-sum. It wasn’t. The merchants we were arguing about hadn’t even gotten to Checkout. The right framing isn’t "which surface wins." It’s "which surfaces, together, cover the population we want to reach."
A photographer paid her invoice. The bank knew nothing about it.