Backend and API Development
Server-side systems and the interfaces other things depend on. Built with the contract written first, because an API is a promise and changing one after it has callers is expensive.
- Who
- Delivered by a senior team assembled for the engagement, against a defined scope.
What you're seeing
- A client team is blocked because the endpoint does not do what they were told it would.
- Usually means The interface was described in conversation rather than specified. The disagreement was always there; integration is just where it surfaced, at the most expensive moment.
- The same validation rule exists in three places and one of them is wrong.
- Usually means Constraints live in application code that not everything goes through. Migrations, admin tools and the console all write directly, and one of them has been writing rows the rules would have rejected.
- Nobody will change the shape of a response because something might depend on it.
- Usually means There is no versioning policy and no inventory of callers, so every change is treated as breaking. The API has become frozen without anyone deciding to freeze it.
Contract first
An API is a promise to something you do not control.
Writing that promise down before the implementation exists means the disagreement happens at review time, in a pull request, between people who can still change their minds cheaply. Writing it afterwards means the disagreement happens at integration time, between two teams with deadlines, and the resolution is whichever side has less slack.
In practice this is a specification the consuming team reviews before anything is built, and then used as the test target so the documented interface and the running one cannot drift apart. Both halves matter: a specification nobody consumes is a document, and a specification nothing tests is a wish.
Constraints belong in the database
Application code is not the only thing that writes to your tables.
Migrations write. Admin tooling writes. The console session someone opened to fix a support ticket writes. A rule that exists only in a service layer is enforced for exactly the paths that go through that layer, which is fewer paths than anyone believes, and the rows that got in around it are discovered later by a report that does not add up.
Adding a constraint to an existing table often fails on the first attempt because there is already data that violates it. That is not an argument against the constraint. It is the count of how long the rule has not really been a rule.
The counterpart to this is the data model itself, which is where most of the expensive decisions are actually made — see Database & Data Modeling.
Where it sits
This is one capability inside Software Development, and on most engagements it is the largest single piece of it.
Where an interface is being built to connect existing systems rather than to serve a product surface, the work belongs with API Integration instead — the difference is whether you own both ends and whether the data model is yours to decide.
Where the question is not how to build the interface but whether the current structure will hold at the scale the plan assumes, that is an Architecture Review, and it is usually cheaper to run first.
How the work runs
-
Agree the contract
The interface specified before implementation, in OpenAPI, and reviewed by whoever will consume it. Discovering a mismatch at integration time is the expensive way to find it.
-
Model the data
Schema, constraints and migration path. Constraints in the database rather than only in application code, because application code is not the only thing that writes.
-
Build against the contract
Implementation with the specification as the test target, so drift between the documented and the actual interface is caught by CI.
-
Version and deprecate deliberately
A stated policy for breaking changes with a deprecation window, agreed before the first external caller exists.
What arrives
- An OpenAPI specification kept in step with the implementation by CI
- Migrations that run forward and roll back
- Integration tests covering the contract, not only the internals
- A written versioning and deprecation policy
What it costs your team
Around four hours a week from a product owner for scope questions, and a named engineer for consumer-side review.
How we decide
The contract is written and reviewed before implementation
Costs It slows the first week and requires the consuming team to engage before there is anything to run.
An API is a promise to something you do not control. Writing the promise down first moves the disagreement to review, where it costs an hour, instead of to integration, where it costs a release. It also makes the specification the test target, so the documentation cannot silently drift from behaviour.
Constraints go in the database, not only in the service layer
Costs It makes migrations harder and occasionally forces a data cleanup before a constraint can be added at all.
Application code is not the only thing that writes to your tables. A rule enforced only above the database is a convention, and conventions are what a one-off script run at midnight ignores. The cleanup that a new constraint forces is not an obstacle — it is the count of rows that were already wrong.
The versioning policy exists before the first external caller
Costs It is work spent on a problem that does not exist yet.
What counts as a breaking change, how long a deprecated version is supported, and how consumers are told are trivial to decide with zero callers and politically impossible with twenty. Retrofitting the policy means negotiating it with people who have already built against the current shape.
Where this has run
Frequently Asked Questions
Sources
- OpenAPI Specificationspec.openapis.org
- Semantic Versioning 2.0.0semver.org
- PostgreSQL — documentationpostgresql.org
- The Twelve-Factor App12factor.net
Page reviewed

