Stripe Production Launch Checklist: 20 Things to Verify Before Going Live
Check Stripe production keys, webhook processing, payment states, customer flows, logging, and monitoring before enabling live payments.
Before accepting live payments, verify environment keys, webhook signatures, durable processing, payment states, and customer-facing recovery flows. Test duplicate and delayed events as well as successful checkout.
Stripe Production Launch Checklist
API Keys and Environment Configuration
-
No secret keys in client-side code or version control. Your
sk_live_*key should only exist in server-side environment variables. Scan repository history and build artifacts for exposed keys. A literal-string search alone cannot prove that no secret was committed. -
Publishable key is scoped to the correct environment. The
pk_live_*key for your production frontend should be different from thepk_test_*key used in development. Confirm your environment variable pipeline sets the right key per environment. -
Restricted API keys where possible. In the Stripe Dashboard, create restricted keys with only the permissions your server needs (e.g., read/write on
PaymentIntentsandCustomers, but notPayouts). This limits blast radius if a key is exposed. -
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
-
Separate webhook endpoints for production and staging. Do not share a single endpoint across environments. Production events should never land on staging handlers.
-
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. -
Webhook handler returns
200before 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, durably enqueue, return200; return an error if durable enqueueing fails. -
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.
-
All critical events are registered. At minimum:
checkout.session.completed,customer.subscription.updated,customer.subscription.deleted,invoice.payment_failed,invoice.payment_succeeded. -
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
-
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. -
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_urlredirect alone. -
Cancel and refund flows work. Test both immediate and period-end cancellation. Update access from the actual subscription state and paid-through policy rather than revoking access for every cancellation request.
-
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
-
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.
-
HTTPS is enforced everywhere. Use HTTPS for live payment pages and webhook endpoints. Confirm your production domain enforces HTTPS including on redirect URLs and webhook endpoints.
-
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
-
Success and cancel URLs handle all states gracefully. A customer who returns to
success_urlwithout 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. -
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
- 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.