Use this guide as a pre-launch gate before you point real traffic at Stripe. It composes the Operations & DX trust rails into a scannable checklist — you verify boundaries here, then follow linked guides for full behavior truth.
Production Stripe integrations fail at boundaries — keys, raw bodies, idempotency, and observability.
Add LatticeStripe to your release:
{:lattice_stripe, "~> 1.7"}1. Audience and scope
This checklist covers SDK integration hygiene for Elixir/Phoenix apps using LatticeStripe — not Stripe Dashboard account setup (business verification, tax settings, payout schedules). For Dashboard readiness, use Stripe's account checklist.
After launch, when webhooks misbehave in production, switch to Event Debugging — this guide is the pre-flight gate, not the post-incident playbook.
2. Quick checklist
Print or copy this block. Each item should be true before go-live:
- [ ] Live secret key (
sk_live_...) loaded from env, never committed - [ ] Test and live keys isolated per environment
- [ ] Finch pool started in supervision tree before first API call
- [ ]
LatticeStripe.Client.new!/1used with explicitapi_keyandfinch - [ ] Webhook endpoint secret resolved at runtime (MFA or env), not hardcoded
- [ ]
LatticeStripe.Webhook.Plugmounted beforePlug.Parsers - [ ] Raw request body preserved for signature verification
- [ ] Idempotency keys on money-moving writes; SDK auto-keys POST by default
- [ ]
%LatticeStripe.Error{request_id: _}logged on API failures - [ ] Telemetry handlers attached for request and webhook verify events
- [ ] Circuit breaker configured (recommended before scale) — see Circuit Breaker
- [ ] Connect platform flows reviewed if you use
Stripe-Accountheader routing - [ ] Smoke tests pass against test mode; one live-mode $0 or refund test if policy allows
- [ ] Operator playbooks bookmarked: Event Debugging, Testing
3. API keys and environments
Never embed secret keys in source. Resolve at runtime:
client =
LatticeStripe.Client.new!(
api_key: System.fetch_env!("STRIPE_SECRET_KEY"),
finch: MyApp.Finch
)Use sk_test_... in dev/CI and sk_live_... only in production deploys. Rotate
keys in Dashboard if any key ever appeared in logs, tickets, or git history.
See Client Configuration and Getting Started for optional client settings and test keys.
4. Client and Finch production wiring
Finch must be running before Client.new! issues its first request:
# application.ex — Finch must start with your app
children = [
{Finch, name: MyApp.Finch},
MyAppWeb.Endpoint
]Pool sizing, timeouts, and connection limits belong in Performance — this checklist only asserts Finch is supervised.
5. Webhook verification and endpoints
Mount the plug before parsers so Stripe signs the same bytes you verify:
# lib/my_app_web/endpoint.ex
plug LatticeStripe.Webhook.Plug,
at: "/webhooks/stripe",
secret: {MyApp.BillingConfig, :stripe_webhook_secret, []},
handler: MyApp.StripeWebhookHandler
plug Plug.Parsers,
parsers: [:urlencoded, :multipart, :json],
pass: ["*/*"],
json_decoder: JasonYour app starts work. Webhooks confirm reality. API responses mean Stripe accepted the request now; webhooks tell you what actually settled, failed, or retried later.
For snapshot /v1 webhooks, see Webhooks. For thin /v2/events,
see Webhooks: Thin Events.
6. Idempotency and safe retries
LatticeStripe attaches idempotency keys to POST requests automatically. For money-moving operations (creates, captures, refunds), pass explicit keys tied to your domain idempotency token so retries do not double-charge:
LatticeStripe.PaymentIntent.create(client, params,
idempotency_key: "pi-create-#{order_id}"
)Combine with Error Handling for retryable status codes and Metering if usage events must not duplicate.
7. Error handling and support posture
On {:error, %LatticeStripe.Error{} = err}, log err.request_id — Stripe support
and Dashboard logs correlate on that value. Do not log full card or bank payloads.
See Error Handling for classification, retry policy, and support escalation patterns.
8. Telemetry and observability
Attach handlers for [:lattice_stripe, :request, :stop] and
[:lattice_stripe, :webhook, :verify, :stop] before launch. You need request
duration, status, and verify outcomes in your metrics stack — not only application
logs.
See Telemetry and OpenTelemetry for handler recipes and export wiring.
9. Resilience (recommended before scale)
Configure circuit breaking and backoff before traffic spikes — not after the first outage. Defaults are tunable; the requirement is that failure isolation is deliberate.
See Performance and Circuit Breaker.
10. Connect platforms (if applicable)
If you route requests with Stripe-Account, verify webhook handlers dispatch on
event.account (or thin-event context) and that money-movement reconciliation
matches your Connect charge model.
See Connect and Connect Money Movement.
11. Final smoke tests
Run the integration paths you ship: checkout or PI confirm, webhook delivery to your staging endpoint, and at least one idempotent retry simulation.
See Testing for stripe-mock, Bypass patterns, and webhook test harnesses — do not duplicate that guide here.
Support and audit lookups
Charge is the result record of a payment attempt, not payment initiation. Use
PaymentIntent for payment flows; use Charge to read/reconcile existing charges.
Full API: LatticeStripe.Charge moduledoc (no separate Charge guide in v1.7).
For support tickets and audits:
- List or filter settled charges:
LatticeStripe.Charge.list/3 - Search by Stripe query syntax:
LatticeStripe.Charge.search/3— results are eventually consistent; do not rely on search for seconds-fresh payments - Connect fee reconciliation: follow balance transaction
fee_detailsvia Connect Money Movement
Route new payment work through PaymentIntent; use Charge modules for read/reconcile only at launch review.
Read next
- Event Debugging — post-incident webhook diagnosis
- Webhooks — snapshot endpoint setup
- Error Handling — errors, retries,
request_id - Testing — CI and local verification
- Telemetry — metrics and event handlers