Skip to content

Ship paid billing (Dodo) on main matching revised pricing (#60); pricing page 404 #66

Closed

Description

@clbotdev

Background

Updated 19 Oct 2026 after the platform migration (#81) landed on main.

Billing is now on main: PR #16 was merged, and billing runs on @codelitdev/billing 0.4.1 with the Platform Dodo adapters. These parts are already in place:

  • Org-wide monthly send accounting: reserveSend runs on marketing (apps/api/src/mail/worker.ts), transactional (apps/api/src/transactional/queries.ts) and outbound sends (apps/api/src/delivery-feedback/outbound-send.ts), and enforces monthlySendsLimit.
  • Per-org limit overrides live in organization_plan_policies (ADR 0002), not in the billing tables.
  • The "Sent with SendLit" footer is driven by marketingBranding.

What is still wrong:

  • apps/api/src/billing/policies.ts still has the old ladder:
    • PlanId = "oss" | "free" | "pro" | "business", with no starter
    • Free: 1,000 subscribed contacts, 3,000 sends
    • Pro: 5 teams, 10,000 contacts, no send cap (fairUse)
    • Business: 25 teams, no send cap (fairUse)
  • That contradicts the revised pricing in Revise hosted pricing plans: Starter, Pro and Business priced on sends and teams, unlimited contacts #60 (Starter $10 / Pro $29 or $39 / Business $99, priced on sends and teams, unlimited contacts). Revise hosted pricing plans: Starter, Pro and Business priced on sends and teams, unlimited contacts #60's open decisions 1-4 are still unanswered.
  • Plan lists in other places only know pro and business: billing.config.ts (planIds, requiredOfferKeys), billing/catalog.ts (catalog keys, BillingPlan, BILLING_* env vars), paidPlan() in policies.ts, packages/api-contract billing schemas, the MCP teams tool, the SDK types and the web Organizations page.
  • Overage is not built. Only teamsLimitOverride and contactsLimitOverride exist; there is no extraSendBlocks or extraTeams.
  • apps/docs/content/docs/workspace/pricing.mdx shows the old table. It also says SendLit "does not sell add-on packs" and that Pro and Business have no send charge.
  • https://sendlit.app/pricing returns 404. The nav links to /#pricing. The marketing site is not in this repo.

Related: #56 (upgrade vs new-org checkout dialog), #57 (Free plan badge), #22 (Dodo webhook quarantine).

This blocks inviting beehiiv switchers: they need to be able to pay for a plan that matches what we advertise.

Proposed fix

  1. Resolve Revise hosted pricing plans: Starter, Pro and Business priced on sends and teams, unlimited contacts #60's open decisions (Pro $29 vs $39, Starter footer, Business tier, migration of existing Pro).
  2. Update policies.ts to the Revise hosted pricing plans: Starter, Pro and Business priced on sends and teams, unlimited contacts #60 table:
    • add starter
    • set subscribedContactsLimit: null on every plan
    • set org-wide monthly send limits on every cloud plan
    • drop fairUse if every paid plan has a hard cap
    • extend paidPlan() to include starter
    • make the monthly_sends limit error report the next plan up instead of always "pro"
  3. Add starter everywhere plans are listed:
    • billing.config.ts, then run codelit-billing generate, add a drizzle migration and keep check:drift green
    • the catalog keys and BILLING_STARTER_* env vars
    • the API contract, REST docs, MCP tools, SDK and dashboard
  4. Grandfather existing orgs before the new limits take effect. Limits come from code, so existing Pro (5 teams down to 3) and Business (25 teams down to 15) orgs over the new team limit need a teamsLimitOverride set in a data migration.
  5. Overage: either ship hard caps that ask users to upgrade and track overage separately, or add a send-limit override and Dodo add-on products now. Hard caps first is recommended.
  6. Remove or keep the now-unused contact-limit enforcement in billing/entitlements.ts. Keep the contacts_limit_override column so the schema stays compatible with the previous release.
  7. Create the Dodo products (monthly and annual) for Starter, Pro and Business. Wire checkout, upgrade (Difference in upgrade and new org checkout dialog #56) and webhooks (Ignore other brands' Dodo webhooks and quarantine unknown products with operation_quarantined #22).
  8. Update apps/docs/content/docs/workspace/pricing.mdx. Publish a pricing page at sendlit.app/pricing, or make the /#pricing section complete, and keep both in sync with the policies.

Acceptance criteria

Activity

  1. zekfer38-netizen commented on Oct 19, 2026

    @zekfer38-netizen
  2. clbotdev commented on Oct 25, 2026

    @clbotdev
    ContributorAuthor

    Closing: paid billing is live on production and matches #60.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestseverity: highMajor gap or broken flow for many users

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions