Architecting and scaling Node.js backends
Node.js scales beautifully — until an architecture that was fine at launch meets real traffic. I design backends that keep responding as load grows, and I have taken one to more than three million signed-up users without it falling over.
Split by load, not by diagram
I draw service boundaries around what actually scales differently — auth, ingestion, AI inference, billing — rather than an org chart. On aichatapp.ai (GPT-4o, Gemini, Claude, Grok, DeepSeek in one product) I built the backend on GCP Cloud Run with Pub/Sub and Firestore; it grew to 3M+ users. On OptAI I used a Bun runtime with Kafka event streaming for the crawl-and-score pipelines.
Streams, queues, cache — in that order
Most scaling problems are back-pressure problems. Kafka or RabbitMQ decouple producers from consumers, BullMQ absorbs spikes, and Redis caching takes the read load off the database. Add tracing and dashboards (Datadog, Sentry, Grafana, PostHog) so you scale from evidence, not guesses.
The right database for each job
One database rarely fits a whole system. I mix PostgreSQL, MongoDB, DynamoDB/Firestore, Elasticsearch and vector stores by workload, and I have run NestJS, Go, Java Spring Boot and Rust services side by side behind a Kong API gateway on Kubernetes when the load justified it.
- Service boundaries drawn around what scales differently — proven to 3M+ users.
- Event streaming, queues and caching to handle back-pressure and spikes.
- Observability first, and the right database per workload.