Skip to content
Writing
Back-endInfrastructure

Boring Infrastructure Is What Makes Speed Safe

The backend foundations I put in place so a team, and the AI agents in its repositories, can ship quickly without breaking what already works.

· 3 min readOn the map: Back-end

A team ships fast when a change is cheap to make, cheap to check and cheap to undo. None of that comes from working harder. It comes from a short list of unglamorous foundations that are in place before the first feature.

These are the ones I set up first, and why they matter more now that AI agents write a share of the code.

Environments are code

Every environment is described in the repository: infrastructure as code for the cloud resources, containers for the services, configuration read from the environment rather than baked into the build. If a server can only be rebuilt by the person who clicked through the console, it isn't infrastructure. It's a memory.

Every branch gets its own preview deployment, as close to production as it can be. Small differences between local and production — a different database engine, a queue that only exists in one of them — are exactly where code that passed every test fails on release day.

Secrets live in a secrets manager and reach the service at runtime. They never sit in the repository or in a .env file passed around in chat. A repository an agent can read is a repository that must not contain credentials.

If it matters, it blocks the merge

Every pull request runs the same pipeline: build, type-check, lint, unit and integration tests, a secrets scan. Each one is a required check, and on the main branch branch protection applies to administrators too. If it doesn't block the merge, it isn't a standard. It's a preference.

Two rules keep the pipeline honest. It has to be fast, because a slow pipeline gets routed around. And a flaky check is fixed or removed as soon as it appears, because every false red teaches the team to treat red as ambiguous.

If an emergency override exists, it is loud — a written reason and a visible notification — so it stays exceptional.

Boundaries are typed, not agreed in a meeting

Every service boundary has a contract that lives in the repository: an OpenAPI document for REST, a schema for GraphQL. Client types are generated from it, never written by hand. A breaking change then shows up where it should — as a compile error in the pull request, not as a support ticket after release.

The contract is also the cheapest documentation a team will maintain, because it can't drift from the code without the build noticing.

The pipeline runs migrations, not people

Schema changes are versioned files, reviewed like code and applied by the deployment pipeline, the same way in every environment. Nobody runs SQL against production from a laptop.

Changes that would break running code go through expand and contract: add the new column, move readers and writers across, remove the old one in a later release. Each step is deployable on its own, so any release can be rolled back without a data emergency.

Async work assumes it will run twice

Anything slow or dependent on a third party — sending email, calling an external API, generating a document — goes through a queue instead of the request. Queues deliver at least once, so every consumer is idempotent: it records what it has processed and treats a repeat as a no-op.

Retries use backoff and a limit. A message that keeps failing moves to a dead-letter queue, and anything landing there raises an alert. A dead-letter queue nobody watches is just a slower way to lose data.

Alert on what users feel

Logs are structured and carry a request ID that follows the work across services and queues, so one failed request can be traced end to end. Dashboards cover the basics: latency, traffic, errors, saturation.

Paging is reserved for symptoms. Google's SRE book separates what is broken from why; I page on the first — errors users see, requests that are too slow, jobs that stopped finishing — and use everything else to diagnose. An alert nobody needs to act on gets deleted.

Why this is what makes AI safe

My team uses AI agents to implement tickets and open pull requests, and a person approves every merge. That model only works on top of this floor. An agent can't hold a large codebase in its head; a typed contract, a fast test suite and a reproducible environment tell it, and the reviewer, when it has broken something it never looked at.

The 2025 DORA research found the same pattern across the industry: AI raises throughput, but without strong automated testing, version control and fast feedback, more change means less stability. AI amplifies whatever system it lands in.

Speed isn't what you gain by skipping the foundations. It's what the foundations give back.