WritingStripe Production Launch Checklist: 20 Things to Verify Before Going Live — Clixo
5 min readstripe, payments, checklist, production, launch

Stripe Production Launch Checklist: 20 Things to Verify Before Going Live

A comprehensive Stripe production launch checklist covering API keys, webhooks, PCI scope, testing, and monitoring before you accept real payments.

Launching a Stripe integration to production without a systematic review is how teams end up with silent webhook failures, live secret keys in frontend bundles, and fulfillment logic that double-provisions on retry. This checklist covers the things that most commonly break — not the happy path, but the edge cases and configuration gaps that only show up under real conditions.

Stripe Production Launch Checklist

API Keys and Environment Configuration

  1. No secret keys in client-side code or version control. Your sk_live_* key should only exist in server-side environment variables. Run git log --all -S "sk_live" to confirm it has never been committed.

  2. Publishable key is scoped to the correct environment. The pk_live_* key for your production frontend should be different from the pk_test_* key used in development. Confirm your environment variable pipeline sets the right key per environment.

  3. Restricted API keys where possible. In the Stripe Dashboard, create restricted keys with only the permissions your server needs (e.g., read/write on PaymentIntents and Customers, but not Payouts). This limits blast radius if a key is exposed.

  4. Webhook secret stored as an environment variable, not hardcoded. Each registered webhook endpoint has its own signing secret. Confirm it is not hardcoded in your source.

Webhook Configuration

  1. Separate webhook endpoints for production and staging. Do not share a single endpoint across environments. Production events should never land on staging handlers.

  2. Signature verification is active on every webhook handler. Use stripe.webhooks.constructEvent() and confirm it throws on invalid signatures — test this explicitly with a forged payload.

  3. Webhook handler returns 200 before processing. If your handler does async work inside the request lifecycle, it will time out under load and Stripe will retry. Confirm the pattern is: verify, enqueue, return 200.

  4. Idempotency guard on all webhook handlers. Stripe can deliver the same event more than once. Confirm you have a unique constraint on the event ID in your processed-events table.

  5. All critical events are registered. At minimum: checkout.session.completed, customer.subscription.updated, customer.subscription.deleted, invoice.payment_failed, invoice.payment_succeeded.

  6. Webhook delivery failures trigger an alert. Set up a Stripe Dashboard alert or a monitoring integration so webhook failures surface within minutes, not days.

Payment Flow Testing

  1. Every card failure scenario is tested. Use Stripe's test cards for declined payments (4000 0000 0000 0002), insufficient funds (4000 0000 0000 9995), and 3D Secure authentication (4000 0027 6000 3184) before switching to live mode.

  2. Success path tested end-to-end in test mode. Verify that checkout completion triggers the webhook, the webhook handler provisions access, and the user sees the correct post-payment state — without relying on the success_url redirect alone.

  3. Cancel and refund flows work. Confirm that cancellation via the Customer Portal triggers customer.subscription.deleted and your handler revokes access correctly.

  4. Idempotency keys are in use on all payment creation calls. Confirm that retrying a failed payment intent creation with the same key does not create a second charge.

PCI Scope and Security

  1. No raw card data touches your servers. If you are using Stripe Elements or Stripe Checkout, card data is tokenized in the browser and never sent to your backend. Confirm no custom form is posting card numbers directly to your API.

  2. HTTPS is enforced everywhere. Stripe's JavaScript library will not load over HTTP. Confirm your production domain enforces HTTPS including on redirect URLs and webhook endpoints.

  3. No card data in logs. Audit your logging pipeline to confirm that payment-related request bodies are not being logged verbatim. Stripe objects include last-four digits and expiry — those are acceptable. Full PANs or CVVs in logs are a compliance violation.

Customer-Facing Experience

  1. Success and cancel URLs handle all states gracefully. A customer who returns to success_url without completing payment (e.g., by navigating back) should not see a broken state. Fetch the session server-side to confirm payment status before displaying confirmation.

  2. Customer Portal is enabled and linked. If you have a subscription product, the Customer Portal must be configured in the Stripe Dashboard and accessible from your app. Customers need a self-serve way to cancel, upgrade, and update payment methods.

Monitoring and Observability

  1. Payment and subscription events are logged to your own database. Do not rely solely on the Stripe Dashboard for your financial record of truth. Every significant event — successful charge, failed charge, subscription change — should create a record in your system.

Running through this list before launch takes two to four hours and prevents the kind of production incidents that take two to four days to diagnose and repair.

If you want a Stripe integration that comes pre-audited against this checklist, Start a build with Clixo.