Router GraveyardJuly 9, 2026

We Chose Polar for One-Time Licenses. Here's the Actual Trade-off Table.

For a local-first, one-time product, the payment processor is part of the product. Polar's license keys and no-pressure economics matched our soul pillars. LemonSqueezy's merchant-of-record model would have pushed us toward subscriptions and away from the thing we are building.

We Chose Polar for One-Time Licenses. Here's the Actual Trade-off Table.

In June 2026, we picked Polar.sh as RoutePlane’s payment processor. The alternative was LemonSqueezy. On paper they look similar: developer-friendly, no-code checkout, hosted tax handling, “we ship the boilerplate so you can ship the product.” In practice they are pointed at different businesses, and the differences show up in the kind of company you end up being.

This is the Router Graveyard angle on a payments decision: the processor is part of the product. The default settings nudge you toward a model (subscriptions, metering, customer-as-revenue-stream) that may be incompatible with what you are building. We are building a one-time, local-first BYOK router. Polar was the match. Here is the actual trade-off table, with the numbers we used at decision time and the flow that runs in production.

Why the processor matters at all

Most payment processors are interchangeable for an online SaaS. For RoutePlane, three properties are non-negotiable and they narrowed the field hard:

  1. One-time payments must be first-class, not the awkward sibling of subscriptions. Recurring billing should not be the default UI, the default pricing page layout, or the path of least resistance.
  2. License keys must be a primitive the processor gives us back, not a feature we have to glue onto webhooks and a separate database.
  3. No pressure to meter usage or take a cut of downstream revenue. If the processor earns more when our customers spend more, we have already lost the BYOK promise.

LemonSqueezy is a Merchant of Record. It invoices customers in your name, handles VAT and sales tax globally, and takes a cut of every transaction. Its billing UI, dunning flows, retention dashboards, and annual defaults are tuned for SaaS subscriptions. It is an excellent product for that surface.

Polar is a Merchant of Record too, but it ships a license_keys benefit as a native object, treats one-time products as a primary type rather than a “no-recurring” checkbox, and prices on a flat percentage rather than rewarding higher customer spend.

That is the structural difference. Everything else is a detail.

The actual trade-off table

Here are the numbers we used at decision time (June 2026), plus a few that have moved since:

Dimension Polar.sh LemonSqueezy
Pricing model 5% + $0.40 per transaction (no platform fee) 5% + $0.50 per transaction (no platform fee)
Payment processing Passed through at Stripe’s published rate (~2.9% + 30¢ US) Bundled into the 5% + $0.50 (uses Stripe + Paddle rails)
Effective total per $49 sale ~$3.00 (≈6.1%) ~$2.95 (≈6.0%)
One-time products First-class product type Supported, but UI nudges toward subscriptions
License keys Native license_keys benefit, returned via API and webhook Not a primitive; you build it from order IDs or external store
Tax / VAT handling Merchant of Record, included Merchant of Record, included
Refunds Self-serve from dashboard, license can be invalidated on the same object Self-serve from dashboard, manual license revoke
Subscription defaults Off by default On by default in checkout UI
Buyer support Resold by Polar as part of MoR (light) Resold by LemonSqueezy as part of MoR
Acquirer / parent Independent (bootstrapped, founded 2023) Acquired by Stripe in 2025; product direction increasingly aligned with Stripe Billing
API ownership Full CRUD on products, benefits, checkout links via REST Full CRUD; some surfaces gated behind partner status

On fees alone the two are within rounding. The decision is not about the percentage. It is about the primitives and the defaults.

What Polar’s license_keys benefit actually gives us

Polar treats a license key as a first-class object. When we create a product (RoutePlane Pro at $49 one-time, RoutePlane Team at $199 one-time), we attach a benefit of type license_keys. After a successful checkout, Polar generates a key, attaches it to the customer record, and surfaces it in three places:

  1. The buyer’s email receipt (with a copy of the key).
  2. The Polar dashboard under Customers → License Keys, with a status and activation count.
  3. The webhook payload we already handle in our Cloudflare Worker.

Our scripts/setup-polar-products.sh script owns this end-to-end. It is idempotent: if the benefit already exists, it reuses it. If a product already exists, it reuses it. If a checkout link already exists, it reuses it. The script then auto-patches src/pages/pricing.astro with the live checkout URLs, so the pricing page never lies. After a real purchase, we look at the dashboard, copy the key format Polar actually emits (it is not the RP-PRO-2026-XXXX placeholder from the docs — it is a real Polar key or order ID), and the buyer’s flow from there is:

1. Pay on buy.polar.sh/...
2. Receive key in email + Polar dashboard
3. Run: routeplane license activate <KEY>
4. Run: routeplane license status → shows truthful Pro status

That is the entire activation loop. No portal. No seat assignment UI. No phone-home. The binary validates the key locally against the format and the activation count, and routeplane status surfaces the result.

If we had built this on LemonSqueezy, every step of step 3 would be something we wrote. Order ID → database row → key generation → email template → webhook handler → revocation endpoint. It is not impossible. It is also not what we want to spend our engineering time on.

One-time vs subscription economics for a BYOK router

A subscription model only makes sense when the provider is in the loop on usage. If we billed $9/month, we would owe the customer ongoing value: a managed control plane, a hosted dashboard, usage-based observability, maybe a managed failover. We would also be tempted to meter their tokens to justify the recurring price. Both of those collide with soul pillar #1.

The honest math for a BYOK router:

  • Customer value: a working router with Fusion, Guardrails, OpenTelemetry, unlimited providers, and server tools.
  • Provider cost to deliver: a binary that runs on their machine. Bandwidth for downloads. License validation. Email support.
  • Recurring cost to us: effectively zero per active license. No per-request compute. No storage growth tied to usage.

Recurring $9/month for a binary that does not get more expensive to support is a bad deal for the customer and a slow-motion alignment disaster for us. We would start optimizing for retention over honesty. We would start shipping features whose only purpose is to justify the renewal.

A one-time $49 license, with license keys as proof of purchase for the current major version, matches the cost structure. Updates within the major version are included because they cost us nothing extra to ship. Major upgrades can be priced separately later, or not.

This is also why we will never do usage metering or token cut. The moment we meter tokens, we are incentivized to make the router slower or less efficient, because every millisecond of overhead is revenue. The moment we take a cut, we are competing with the providers on price instead of competing with the providers on policy. Both incentives corrupt the product.

Customer experience: checkout, refunds, support burden

A one-time product is dramatically less work to support than a recurring one. The numbers are not subtle:

  • Checkout: Polar-hosted page, Apple Pay / Google Pay / card, MoR handles VAT. The buyer never sees our domain until after the payment clears.
  • Receipts and tax forms: Polar’s MoR emits them. We do not write a single line of compliance code.
  • Refunds: one click in the Polar dashboard invalidates the license. The buyer’s routeplane license status reflects it on next run. No Stripe API call, no database update, no email back-and-forth.
  • Support volume: dunning emails, failed card retries, “why am I still being charged,” cancellation flows — none of it exists. The support queue is about the router, not the billing.
  • Chargebacks: Polar’s MoR absorbs the operational burden for transactions it processed. We are notified, not asked to submit evidence.

A subscription on LemonSqueezy would have given us the same MoR benefits, plus all of the recurring billing machinery we explicitly do not want. The support burden math is not close.

Why we own the commercial surface via a script, not a dashboard

One more detail worth naming. We did not hand-create the products in the Polar dashboard. We wrote scripts/setup-polar-products.sh to do it via the API, idempotently, with jq and curl. The same script auto-patches src/pages/pricing.astro with the live checkout URLs. The result:

  • Two products, one benefit, two checkout links, one pricing patch — all from a single command.
  • Re-running the script does not duplicate anything. Searching by name and benefit description catches collisions.
  • The commercial surface is reproducible from source. Anyone with a POLAR_TOKEN can recreate the entire storefront without clicking through a UI.

This matters more than it sounds. A dashboard is a snapshot. A script is a contract. If Polar changes a field, if a product gets archived by accident, if we want to spin up a sandbox mirror for testing — we re-run the script. The pricing page and the Polar dashboard cannot drift, because the script is the only writer.

The honest path

We could have run RoutePlane as a $9/month subscription on LemonSqueezy and probably made some money in the short term. We could have layered a usage meter on top and charged a fraction of a cent per token. Both of those would have optimized for the same outcome: more revenue from existing customers, with the router itself becoming secondary to the billing relationship.

That is not the router we are building.

The router we are building is local-first, BYOK, one-time, and license-as-proof. Polar lets us ship that with the primitives we needed (license keys, MoR, no subscription defaults) and without the gravity of a SaaS-shaped tool trying to reshape us into its customer. The processor is part of the product. Ours points at the same thing we point at.


CTA: This is why Pro is $49 once, not $9/mo. See pricing or the activation guide.

Sources and references (as of 2026-07): Polar.sh public pricing page and benefits API documentation (license_keys benefit type, 5% + $0.40 per transaction); LemonSqueezy public pricing and merchant-of-record documentation at decision time (5% + $0.50 per transaction, subscription-first checkout defaults); Stripe published US card processing rates used in the effective-cost calculation; our own scripts/setup-polar-products.sh as the single source of truth for product creation, benefit attachment, checkout link generation, and src/pages/pricing.astro patching. Specific transaction-volume tiers, partner-only rates, and post-acquisition LemonSqueezy roadmap details are not referenced where public confirmation is incomplete.