APIs designed for their consumers
REST or GraphQL, chosen for the clients that will use it rather than by preference. Consistent error handling with correct status codes, pagination that works on large collections, and versioning in place before you need it β because retrofitting versioning while clients are live is painful.
Data models that survive the next feature
Schema design with the queries you will actually run in mind, appropriate indexing, and migrations that are reversible. We use relational, document or graph databases according to the shape of the data rather than habit.
Authentication and authorisation, kept separate
Session or token authentication implemented against current practice, and a permission model that is checked on the server for every request. Conflating who you are with what you may do is one of the more common causes of access-control bugs.
Integrations that fail loudly
Third-party connections with retries, backoff, idempotency and dead-letter handling, plus alerting when something stops. A failed integration should page someone, not accumulate silently.
Background work and scheduling
Queues for anything slow, unreliable or spiky β imports, exports, document generation, notifications β so a user request never waits on a third party.
Observability from the first deploy
Structured logging, health checks and metrics on the paths that matter. Diagnosing a production issue should be a query, not an archaeology exercise.