The question this answers
What is infrastructure for, and how do I decide what a given workload actually needs?
A team has a working application — an HTTP API and a relational database, correct and fast on a developer's laptop. It must now answer requests from people the team will never meet, at 03:00, after that laptop has been closed and put in a bag.
A place for the process to run that outlives the person who started it, an address other machines can find without being told, storage that survives a restart, an identity the workload can prove to other systems, and a way to replace the running version without stopping the service.
Infrastructure is what the laptop was giving you for free
On a laptop the application looks self-sufficient. It is not. The operating system was scheduling it onto cores, giving it a private address space, resolving localhost to a loopback interface, letting it open a file because *you* were logged in, and — critically — there was a human sitting in front of it who noticed when it crashed and pressed the up arrow and Enter. Every one of those services is real, and every one of them disappears the moment the workload has to run somewhere nobody is watching.
So the honest definition: infrastructure is the set of guarantees a workload needs in order to keep running when the conditions it was developed under are gone. Not "servers". Not "the cloud". A list of guarantees — each one of which has to come from somewhere, be paid for, and have an owner who gets paged when it stops holding.
This framing matters because it makes the first question of every infrastructure decision a *workload* question. Not "should we use Kubernetes" but "what does this workload need that it is not currently getting, and what is the smallest thing that provides it". Workload-First Thinking turns that instinct into a method.
| What the workload needs | On a laptop | In production, someone must provide |
|---|---|---|
| Execution | Your shell started it; you restart it when it dies | A supervisor that starts it on boot and restarts it on exit — see The Instance Lifecycle |
| Reachability | localhost:3000, known only to you | A stable name and address that survives the instance being replaced |
| Durable state | A file in your home directory, backed up by your laptop backup | Storage with an explicit durability and backup contract — see Object, Block and File |
| Identity | Your logged-in user, trusted by everything on the machine | A credential the *workload* can prove, distinct from any human — see Human vs Workload Identity |
| Configuration | A .env file you edited by hand | A delivery path for config and secrets that is auditable and rotatable |
| Change | Ctrl-C, edit, run again | A deployment that swaps versions without dropping requests — see Four Ways to Replace Running Code |
| Observation | You, watching the terminal | Signals that reach a human who is not looking — see Infrastructure Observability |
The smallest honest production shape
Write down the seven guarantees and the topology draws itself. An HTTP API with a relational database needs: something to run the process, a stable entry point in front of it so the address survives instance replacement, a network boundary so the database is not reachable from the internet, durable storage under the database, an identity for the API to authenticate to the database and anything else, and a signal path out. That is six components, and there is no product name in the list yet.
Notice what is *not* here. No orchestrator: one process on one instance does not need a scheduler. No cache: nothing has demonstrated a read-latency problem. No message queue: nothing is asynchronous yet. No second region: no requirement has been stated about surviving one. Each of those is a real answer to a real problem, and none of those problems exist in this workload today. Adding them now is No Cargo-Cult Infrastructure in reverse.
The one thing this shape deliberately does *not* provide is survival of a single instance failing. That is a conscious, documented gap, not an oversight — and it is exactly the kind of gap that should be written down next to the diagram, because the moment the business states an availability requirement, that gap becomes the next thing you fix.
The catalogue trap
The failure mode this domain exists to prevent is designing infrastructure by reading a provider's service list and picking the impressive-sounding entries. It produces diagrams that are technically valid and organizationally fatal: a five-person team owning a control plane, a service mesh, a multi-region database and a streaming platform, in support of an API doing 40 requests per second.
The tell is that nobody can answer *what problem forced this*. Every component in a production system should have a one-sentence answer to that question, and if the answer is "it is best practice" or "we might need it later", the component is a liability with a monthly bill. Complexity is not free and it is not reversible on a normal schedule — you can add Kubernetes in a sprint and you will spend two quarters removing it.
The right-sized version below is not "simpler because simple is nice". It is simpler because every guarantee the workload actually asked for is still provided, and nothing else is.
managed Kubernetes cluster (3 control-plane nodes) service mesh + sidecar per pod ingress controller + cert manager 6 microservices (one team) Kafka cluster (used for one email notification) Redis cluster (no measured cache miss problem) multi-region database with async replication data warehouse + streaming ETL unanswered: which requirement forced ANY of this?
load balancer (TLS termination, stable address)
2 application instances, 2 zones <- forced by: one restart must not be an outage
managed relational database, automated backups
<- forced by: losing customer data is unacceptable
object storage for uploads <- forced by: files must survive instance replacement
workload identity, no static keys <- forced by: a leaked key must expire on its own
metrics + logs + one alert on error rate
<- forced by: nobody is watching at 03:00
every line names the problem that created itThe second design provides every guarantee the workload stated and none it did not. It is also the design a five-person team can actually operate, which is a technical property, not a soft one: infrastructure nobody has the capacity to run is infrastructure that will be run badly.
Key points
- Infrastructure is the explicit provision of guarantees a laptop was giving the workload implicitly: execution, reachability, durability, identity, configuration, change and observation.
- Every component in a production system must have a one-sentence answer to "what problem forced this?" — no answer means no component.
- The right first design is the smallest one that provides the stated guarantees, with the unmet ones written down beside it rather than hidden.
- Choosing infrastructure from a provider's service list inverts the derivation and produces systems a team cannot operate.
- Complexity is asymmetric: it is added in a sprint and removed over quarters.
The loop, answered
Every field is required, which is why no lesson here can recommend something without saying what it costs and what simpler thing to consider first.
- • Start from the application: list what it does, what it stores, who calls it, and what must remain true if a machine dies mid-request.
- • Translate each item into a capability — "must not lose an accepted order" becomes durable, backed-up storage plus an acknowledgement the client can trust.
- • Map each capability to the smallest component that provides it, preferring a managed one when the operational work is not where your team adds value.
- • Record the capabilities you have deliberately *not* provided, with the trigger that would make each one necessary.
- • Only then attach product names; the names are an implementation detail of a design that already exists.
- • Ownership of every guarantee, including the ones a managed service appears to hand you — see Shared Responsibility.
- • The capacity choice: nothing chooses instance size, replica count or storage tier for you, and the defaults are rarely right for your workload.
- • The list of deliberate gaps, reviewed when requirements change, because "we accepted single-instance risk" ages badly in silence.
- • The bill, which is a design artifact and not an accounting one — see Cost Engineering.
- • A guarantee nobody claimed: logging works in every environment except production, because the sink was configured on someone's laptop.
- • A guarantee that was assumed to come with a managed service and did not — most commonly backups that exist but have never been restored.
- • The instance dies and the process does not come back, because "supervision" was a human, and the human is asleep.
- • The design is correct and unoperable: the topology assumes a platform team that the organization does not have.
- • The first thing that runs out is almost never CPU. It is a connection limit, a single instance that cannot be restarted without downtime, or a person.
- • Each guarantee scales differently: reachability scales by adding instances behind the same address, durability scales by replication, and identity scales by policy discipline rather than by capacity.
- • Organizational scale drives infrastructure change more than traffic does — the move from one team to six is what forces deployment independence, not the request rate.
- • The trust boundary is the first thing to draw and the first thing to get wrong: on a laptop everything is inside it, in production the internet is one hop from the load balancer.
- • Ambient authority disappears. The workload needs an identity of its own; borrowing a human's credentials is the single most common early mistake — see Roles vs Static Keys.
- • Exposure needs context, not reflex. A load balancer answering on 443 is the design. A database answering on 5432 from the internet is the finding.
- • Everything that was a local file — config, credentials, TLS material — now has a delivery path, and that path is part of the attack surface.
- • Cost shape follows the design, and the design is made in the first week. Retrofitting cost awareness onto a running system is far harder than deriving it.
- • Fixed components (a load balancer, an idle instance, a NAT device) bill whether or not anyone uses the system; usage components (egress, storage, requests) bill with traffic — see Fixed vs Variable Cost.
- • The largest early cost is usually people: a design that needs continuous human attention is expensive in a way no invoice shows.
- • Whether the application answers, from outside the network, on the path a real user takes.
- • Whether the process is running *and* serving — those are different questions, and confusing them is the subject of Liveness vs Readiness.
- • Whether the durable thing is actually durable: backup completion is a signal, backup *restore* is the proof — see Restore Testing.
- • The signal that lies: a green internal health check on an instance that no traffic can reach, because the failure is in the entry point rather than the process.
- • A managed application platform that provides all seven guarantees behind one deploy command. For a small team with a standard web workload this is frequently the correct answer and stays correct for years.
- • A single virtual machine with a process supervisor and automated database backups, for an internal tool with a known small audience and a tolerable maintenance window.
- • Static hosting with no server at all when the workload turns out to be a site plus a couple of API calls to third parties — the static-website case study works this through end to end.
- • Not deploying yet. If the application has no users, the correct infrastructure is a laptop and a plan, and every hour spent on topology is an hour not spent finding out whether anyone wants it.
- • Deriving from the workload is slower up front than copying a reference architecture, and it produces a design the team can explain and defend.
- • The smallest correct design leaves visible gaps, which is uncomfortable — but a written gap is manageable and an unwritten one is an incident.
- • Managed services reduce operational work and increase both the bill and the dependence on one provider; that is a real trade, not a free win.
What people believe, and what is true
Infrastructure means cloud.
Infrastructure is the set of guarantees. A rack in a room, a rented dedicated server and a hyperscaler all provide them, at different costs and with different work left to you — see On-Premises vs Cloud.
Start with a reference architecture and remove what you do not need.
Nobody removes anything. Subtraction requires proving a component is unused, which is harder than never adding it; reference architectures are written for the largest plausible reader.
Getting this right early does not matter, we can migrate later.
Data gravity and operational habit make migration expensive within months. The database engine and the network boundary in particular are decisions that outlive several rewrites of the application.
Go deeper
Overview
Infrastructure is what has to exist for code to keep running when the developer is not there. Derive it from the workload, one guarantee at a time.
Practical
For each of execution, reachability, durability, identity, configuration, change and observation, name the component that provides it and the person who owns it. Write down the ones you skipped and what would force them.
Advanced
Treat the design as a set of failure statements rather than a set of boxes: "one instance restarting is an outage", "a zone failure loses the write path", "a leaked key is valid until someone notices". Each statement is either accepted with a reason or fixed with a component whose cost you can state.
Internals
Every guarantee ultimately reduces to a mechanism taught in another domain: execution to process scheduling and isolation, reachability to routing and name resolution, durability to write ordering and replication, identity to cryptographic credential exchange. Cloud infrastructure is the packaging and pricing of those mechanisms, which is why a provider outage looks exactly like the underlying mechanism failing.