Before You Accept Real Payments
This checklist covers everything you need to do before accepting real payments. Work through each section in order — skipping a step may cause issues with live transactions.Prefer managed infrastructure? Recurso Cloud handles hosting, scaling, backups, and SSL so you can skip most of this checklist. Compare plans
1. Switch to Live API Keys
During development you use test-mode keys (prefixedrzp_test_ / sk_test_). For production, generate and configure live keys.
.env
2. Configure Payment Gateways
Razorpay (India)
- Log in to Razorpay Dashboard and switch to Live Mode
- Complete KYC verification (required for live payouts)
- Copy the live Key ID and Key Secret to your environment
- Enable auto-capture in Razorpay settings so payments are captured immediately
Stripe (Global)
- Activate your Stripe account (requires business verification)
- Copy the live secret key and webhook signing secret
- Create a webhook endpoint in Stripe pointing to your Recurso instance:
https://your-domain.com/webhooks/stripe
3. Set Up Webhook Endpoints
Configure production webhook URLs in Recurso to receive billing events.The examples below use
https://api.recurso.dev as a placeholder for your Recurso instance. Substitute the domain where your deployment is hosted.- Returns
200status within 5 seconds - Validates the
X-Recurso-Signatureheader (see Webhooks guide) - Handles duplicate deliveries idempotently
4. Enable E-Invoicing (India)
If you are registered under India’s GST e-invoicing mandate (turnover above the threshold), configure your IRP credentials.5. Configure DNS and HTTPS
Ensure your Recurso instance is accessible over HTTPS with a valid TLS certificate.Reverse Proxy Example (nginx)
6. Environment Variables for Production
Review all environment variables before launch..env
7. Monitoring and Alerting Checklist
Set up monitoring to catch issues before your customers do.Built-in Health Alerting
The API ships with a health watcher: every 60 seconds it evaluates the same component checks asGET /health (PostgreSQL, Redis if configured,
TigerBeetle) and POSTs an alert to ALERT_WEBHOOK_URL on state
transitions only — one alert when a component goes down (PostgreSQL =
critical, Redis/TigerBeetle = warning), one when it recovers. No
repeats while the state is steady, and no alerts at all if the variable
is unset.
.env
json→{"severity", "title", "body", "source": "recurso", "timestamp"}slack→{"text": "[SEVERITY] title — body"}(Slack incoming webhooks)
External Monitoring
1
Health check endpoint
Monitor
GET /health on your Recurso instance. Alert if it returns non-200 for more than 2 minutes.2
Webhook delivery failures
Track webhook response codes. Alert on repeated 4xx/5xx responses — failed webhooks mean your app is not processing billing events.
3
Payment failure rate
Monitor the ratio of
payment.failed to payment.succeeded webhooks. A sudden spike may indicate a gateway issue or expired credentials.4
Database backups
Verify that automated database backups are running. Billing data is critical — test restoring from a backup at least once.
5
Log aggregation
Ship Recurso logs to a centralized service (Datadog, Grafana, CloudWatch) for debugging production issues.
Incident Response
Before going live, read the SEV1 incident runbook (the canonical copy lives in the main repository). In short:- Severities — SEV1: money moved wrongly or ledger integrity is broken; SEV2: payments degraded (money that should move, isn’t); SEV3: non-money functionality broken. When unsure, treat it as one level higher until the reconciliation report says the ledger is clean.
- SEV1, in order — stop the bleeding (there is no partial kill-switch
for individual workers; stopping outbound charges means stopping the API
process), snapshot Postgres and logs before touching anything, verify
ledger integrity with
GET /v1/finance/reconciliation, then check the gateway dashboards — Stripe/Razorpay are the source of truth for money that actually moved. - Recovery — restore from
pg_dump, replay missed gateway webhooks from the gateway dashboards (handlers are idempotent on payment state), and re-run reconciliation before re-enabling traffic.
8. Migrate Existing Subscribers (optional)
Moving from Stripe Billing, Chargebee, or spreadsheets? Thecmd/import
tool in the main repository loads plans, customers, and subscriptions
directly into the database — without generating invoices or calling
payment gateways, so migrated customers are never double-billed
mid-cycle. Each imported subscription keeps its original billing period;
Recurso issues the next invoice at its current_period_end.
The import is idempotent — plans match by
code, customers by email,
subscriptions by external_id (the ID from your old system). Re-running
skips anything that already exists, so partial failures are safe to retry.cmd/import/example.json in the repo) or CSVs via
-plans-csv, -customers-csv, and -subscriptions-csv.
Pre-Launch Checklist
Use this checklist to verify everything is ready:Next Steps
Developer Settings
Configure API keys, rate limits, and tenant settings
Idempotency
Ensure your integration handles retries safely
Recurso Cloud
Skip infrastructure management with managed hosting