What the Backend Is Responsible For
The list of duties that cannot be delegated to a client, a framework or a managed service.
The requirement, the obvious build, and why it breaks
Every lesson starts where the work starts: someone asked for something, and the first implementation that comes to mind has a problem.
Which responsibilities are the backend's alone, no matter what else the system uses?
The team is deciding what to build, what to buy, and what the frontend can handle. Someone has to say which parts are not negotiable.
Whatever the framework or platform does not do for us is our job. Everything else is handled.
Managed services move the boundary of responsibility; they do not remove your half. A managed database still leaves you owning connection limits, migrations and query shape.
- Managed services move the boundary of responsibility; they do not remove your half. A managed database still leaves you owning connection limits, migrations and query shape.
- Authorization is never provided by a framework, because only your domain knows who may see what.
- A gateway that does authentication does not do authorization, and teams routinely believe it does (Authentication vs Authorization).
What is actually happening
- Correctness of state — the backend is the only place that decides what is true. Clients propose; the server disposes.
- Authorization — every read and write is permitted or refused here, per caller and per object (Object-Level Authorization).
- Durability boundaries — what is committed, what is queued, what is best-effort. Only the backend knows.
- Failure handling — deciding what a dependency failure means for the caller (An Error Taxonomy That Maps Cause to Response).
- Observability — nothing downstream can reconstruct what your code did unless it says so.
- Resource limits — pools, concurrency caps, payload sizes and rate limits are yours to bound (Resource Limits).
The non-delegable list
Some responsibilities can be bought, moved to a platform, or pushed to a library. These cannot, because they depend on knowing what your data means.
| Responsibility | Can a platform do it? | What remains yours |
|---|---|---|
| Authentication | Largely, via a gateway or identity provider | Session lifetime, revocation, what identity means to your domain |
| Authorization | No | Every rule — it needs your objects and your roles |
| Validation | Shape only, via a schema | Business rules and cross-record consistency |
| Durability | Storage, yes | What must commit together (Where the Transaction Boundary Goes) |
| Failure semantics | No | What a dependency outage means to the caller |
| Observability | Collection and storage | Emitting anything meaningful in the first place |
| Resource limits | Some, at the edge | Pools, concurrency, payload and job limits inside |
Where teams hand off responsibility by accident
These are not exotic mistakes. Each one is a reasonable inference from a true statement, which is exactly why it survives review.
| Trigger | Symptom | Cause | Response |
|---|---|---|---|
| Gateway does JWT validation | Any authenticated user can read any object | Authentication was mistaken for authorization | Enforce object-level checks where the object is loaded (Object-Level Authorization) |
| Managed queue advertises delivery guarantees | Duplicate charges after a redelivery | Delivery semantics conflated with processing semantics | Make consumers idempotent (Job Idempotency) |
| ORM handles the database | Requests pile up at 200 concurrent, all waiting | Nothing bounded concurrency; the pool did, silently | Size and monitor the pool deliberately (Connection Pools) |
| Framework has a default body limit | A 10 MB upload OOMs one instance | A default was treated as a tuned control | Set limits per route against real payload sizes (Request Bodies and Streaming) |
How to build it
Most important first.
- Write the list for your own service and check each item has an owner in code, not in intention.
- For every managed dependency, state explicitly what it does and what remains yours — the gap is where incidents live.
- Enforce authorization at the layer that loads the object, not at the edge, so no route can bypass it.
- Treat observability as a deliverable of the feature, not a follow-up ticket.
What can go wrong
- Assuming the API gateway authenticated *and* authorized.
- Assuming a managed queue guarantees exactly-once business processing — delivery and processing are different guarantees (At-Least-Once Delivery).
- Assuming the ORM bounds concurrency. It bounds nothing; the pool does (Connection Pools).
- Assuming a framework's default body limit is a security control tuned for you.
- Authorization cannot be delegated to a client, a proxy or a model. It requires domain knowledge only your code has (Where the Check Belongs).
- Input validation belongs to the service that acts on the data, even when a caller "already validated it".
- Audit — who did what to which object — exists only if you write it.
- "Managed means handled." Managed means someone else runs the software. The semantics are still yours.
- "The gateway handles auth." It usually handles authentication. Authorization needs your data.
- "The client already validated." The client is one of several, and can be replaced by curl.
Operating it
- For each responsibility, name the signal that proves it is happening: authorization denials counted, validation failures logged, pool saturation graphed.
- A responsibility with no signal is an assumption.
- Responsibilities do not shrink with scale; they get harder to see. At one instance you can reason about state; at fifty you need the signals.
- Buying a managed service moves operational load, not accountability. The pager still rings here.
- Enforcing everything in one service is simple and becomes a bottleneck for team velocity; distributing it multiplies the places a rule can be missed.
- Deep audit and observability cost storage and write throughput.
Where this applies
Backend advice is context-sensitive. These labels say what each claim is specific to, and where a different stack or scale would differ.
- GENERALApplies to any server-side system regardless of stack.
- CLOUD-SPECIFICManaged offerings move the boundary differently — a serverless platform takes over process lifecycle and scaling but hands back cold starts and execution limits, while a managed database takes over failover but leaves you the connection budget.
Where the depth lives
This domain teaches the application-side mechanism and hands the rest off.