Stripe Architecture Deep Dive: Why Rust (Axum + SQLx) Beats Go (sqlc) for Billing Systems
*Translation and summary of a Chinese tech-forum post analyzing billing-system architecture at Stripe scale. Claims below are from the original post, based on an attributed 2026 report by Dagger.*
Background: This Is Not Toy CRUD
The post argues that a Stripe-style billing system faces extreme real-world constraints:
- 10M+ requests per second — unpredictable traffic spikes and webhook floods
- Sub-millisecond latency targets with strong consistency requirements
- Retry storms — failure retries can instantly collapse fragile connection pools
- Constant schema churn — metadata, indexes, and fields change daily
- No codegen — schema changes don't require full binary rebuilds; bottlenecks are solved at runtime rather than compile time
- Async prepared statements —
pool.prepare_cached()automatically reuses query plans; SQL is checked at compile time, results extracted at runtime - JSONB + generated columns — Postgres features enable zero-downtime schema evolution
- Weeks 1–2: SQLx async foundations — async prepared statements, pooled transactions, understanding Postgres behavior over Rust syntax
- Weeks 3–4: Axum CRUD — build Invoices/Customers APIs, integrate Tower middleware (auth, rate limiting)
- Weeks 5–6: Schema evolution strategy — JSONB metadata, generated columns for query optimization, zero-downtime migrations without regeneration
- Weeks 7–8: Load testing & launch — wrk2 benchmarks at 1M+ RPS, compare against legacy system (Fiber + sqlc); capstone: deploy a Stripe-style billing API on Fly.io
- Axum + SQLx billing API, 1.8M RPS, p99 < 1ms
- sqlc → SQLx migration: memory 4.2GB → 1.6GB, 3x throughput
The Conflict: The "Hidden Tax" of Go sqlc
While sqlc's type safety is pleasant in small projects, the author argues it becomes operational hell in a frequently changing billing system:
Go + sqlc cycle (pain points):
1. Schema change (add column / change index)
2. sqlc generate (code regeneration)
3. Full binary rebuild
4. Redeploy & restart (service interruption risk)
Consequence: under high concurrency, struct-mapping overhead grows, goroutine scheduling pressure increases, and connection pools can crash.
Rust Axum + SQLx advantages:
Benchmark Results (Billing API CRUD, 10K concurrency)
| Metric | Rust (Axum + SQLx) | Go (sqlc) | Delta | |---|---|---|---| | Throughput | ~3x baseline | baseline | +3x | | P99 latency | 0.6 ms | 1.9 ms | -68% | | Memory (after migration) | 1.6 GB | 4.2 GB | -62% | | Connection pool under 50K req/s burst | Stable, no thrashing | Thrashing | — |
Load testing was performed with wrk2 at 1M+ RPS targets.
The Production Stack Blueprint
1. Axum Routes — /invoices, /customers
2. Tower Middleware — auth, rate limiting, tracing
3. SQLx (async) — prepared statements, connection pooling
4. Postgres + JSONB — read replicas, PgBouncer
60-Day Migration Roadmap
Conclusion
The author's thesis: engineers who choose Axum + SQLx well aren't paid for syntax knowledge but for avoiding real production incidents. Suggested resume highlights from the post: