Backend Scale: run it for many.
- Users
- Many clients across products
- Team
- Six or more engineers across teams
You are here if
- More than one team deploys backend code independently
- Data lives in more than one region or under residency rules
- An auditor will ask who changed what
- Latency and throughput are contractual, not aspirational
At scale the backend becomes a set of services with explicit contracts, and the language choice starts to matter for reasons beyond taste. Compiled, statically typed languages give the agent a compiler as a second reviewer, and their conventions are strong enough that generated code tends to look like the code around it.
Every service owns its schema, exposes a generated contract, ships with structured logs and traces, and has a test command that runs in isolation. The agent works inside one service at a time and trusts the contract for the rest.
What does not change: small handlers, side effects as jobs, and tests before changes. Scale adds boundaries; it does not change the unit of work.
Product API · serves web & mobile
Go services + Postgres, Rust where latency is the product
Compiled, typed services with a generated contract each, boring infrastructure, and a compiler as the second reviewer.
The stack
- Framework
- Go with chi or Echo; Rust with Axum for the hot path
- Runtime
- Static binaries in containers
- Data
- Postgres per service via sqlc (Go) or sqlx (Rust), Redis or NATS between services
- Auth
- OIDC at the gateway, service-to-service mTLS or signed tokens
- Hosting
- Kubernetes or Nomad, a gateway in front
- Also
-
- OpenAPI or protobuf per service, generated clients
- OpenTelemetry everywhere
- Contract tests between services
Why agents do well here
4/5- Go's formatting and small language make agent-written code indistinguishable from the team's, which is what code review at this size depends on.
- Generated contracts per service let the agent work inside one service and trust the rest.
- The compiler and sqlc's typed queries catch the class of errors an agent introduces most in dynamic languages.
Avoid at this tier
- A service per noun; a service per team boundary.
- Rust everywhere for consistency; use it only where p99 latency is the product.
- Sharing databases between services; share contracts and events.
Data & AI · pipelines & jobs
ClickHouse + a typed ingestion layer + Postgres
Analytical storage separated from transactional, with typed ingestion and a query layer the product reads through one client.
The stack
- Framework
- Ingestion in TypeScript or Python, query API in Next.js route handlers or FastAPI
- Runtime
- Workers or containers for ingestion, an API for reads
- Data
- ClickHouse for events and analytics, Postgres for entities, object storage for raw
- Hosting
- ClickHouse Cloud or self-hosted, Kafka or a managed stream in front
- Also
-
- Schema registry for events
- dbt or SQL models for derived tables
- Data quality checks in CI
Why agents do well here
3/5- Typed event schemas in a registry give the agent one place to learn what flows through the system.
- SQL models in the repo are explicit and testable, so the agent can change a derived table and run its checks.
- Separating analytical from transactional storage keeps each query path simple enough to reason about.
Avoid at this tier
- Analytical queries on the transactional Postgres.
- Untyped event payloads; every event has a versioned schema.
- A new pipeline framework per team; one ingestion layer, many models.
Internal · tools & automation
Rails + Postgres + Redis
The most convention-heavy full-stack framework there is, which at scale is exactly what keeps many teams' internal tools consistent.
The stack
- Framework
- Ruby on Rails 8.1 with Hotwire
- Runtime
- Ruby in containers
- Data
- Postgres, Redis for Sidekiq and cache
- Auth
- SSO through OmniAuth, roles in the database
- Hosting
- Kamal on your own hosts, or a container platform
- Also
-
- Sidekiq for jobs and schedules
- Administrate or a home-grown admin per domain
- RSpec with a real database
Why agents do well here
5/5- Rails conventions are the strongest in the industry; agent-generated models, controllers and migrations follow them almost without prompting.
- Hotwire keeps screens server-rendered, so an internal tool with hundreds of screens has no client build for the agent to fight.
- The framework's opinion about where everything goes is what keeps a large internal platform consistent across teams.
Avoid at this tier
- A JavaScript frontend for internal screens; Hotwire covers it.
- Service objects for everything; models and jobs are enough until they are not.
- Multiple Rails apps; use engines or namespaces in one.