Pre-launch checklist
Run through this before going live. Each item links to the relevant section below.1
Replay protection configured for multi-instance
Default adapter is in-memory only. If you run more than one process (Gunicorn workers, PM2 cluster, Kubernetes), set
SUPABASE_URL + SUPABASE_ANON_KEY or use RedisReplayAdapter. Details →2
Environment variables in secrets manager
Never hardcode API keys. Use
.env locally, secrets manager in prod. Details →3
Health check endpoint exists
Monitoring pings must not trigger invoice creation. Add a
/health route before your paid routes. Details →4
Error responses don't leak internals
Catch provider errors and return a clean 503 — not a stack trace. Details →
5
Price is intentional
priceSats should reflect real value. At 1 sat ≈ 0.06 for a premium endpoint is reasonable. Don’t set it to 0 by accident.6
Uptime monitoring on the invoice endpoint
Monitor the 402 response (it’s a normal response, not an error). Tools like UptimeRobot support custom status code expectations.
7
Rate limiting on invoice creation
Every unauthenticated request creates a Lightning invoice. Without rate limiting, an attacker can exhaust your provider’s invoice quota for free. Add
express-rate-limit before deploying publicly. Details →Critical: replay protection in production
Environment variables
Never hardcode keys. Always use environment variables:Payment logging (Supabase)
Log every payment to Supabase for the VS Code extension dashboard and analytics:Cloudflare Workers deployment
l402-kit API runs on Cloudflare Workers (V8 isolates, zero cold start). The in-memory replay store resets per isolate — for high-traffic APIs, use Cloudflare KV or Durable Objects for replay protection.Docker
User data deletion
Expose a deletion endpoint so users can permanently remove their data. The l402-kit backend includes/api/delete-data out of the box:
Error handling
Catch provider errors before they surface as unformatted 500s:- Never return stack traces to clients — log them server-side.
- Provider timeouts (503) are transient — safe to retry with backoff.
- Token errors (401) are never transient — don’t auto-retry, require a new invoice.
- Rate limit errors (429) — surface the
retryAfterfield to the caller.
Rate limiting
Every unauthenticated request triggerscreateInvoice() on your Lightning provider. Without rate limiting, anyone can flood your endpoint and exhaust your provider’s API quota for free — even without paying a single sat.
Add express-rate-limit before your L402 routes:
Already-paying clients are skipped by the
skip function — the limit only applies to unauthenticated calls that trigger a new invoice. Legitimate payers are never throttled.Health check endpoint
Always add a free health check so monitoring tools don’t trigger invoice creation:Monitoring
Key metrics to track:- 402 response rate — healthy baseline is high (most callers need to pay)
- Payment verification rate — ratio of paid vs unpaid calls
- Provider latency —
blink.createInvoice()should be < 500ms - Replay attempts — spike indicates token reuse attacks
Performance
- Token verification is O(1) — pure crypto, no DB, no network
- Invoice creation (402 path) calls your Lightning provider API — add a cache if you expect the same endpoint hit repeatedly before payment
- Replay store is in-memory
Set— for multi-instance deployments, swap for Redis