Backend Engineering and API DesignIntroductionBackend engineering is the discipline of designing and operating the server-side systems that store data, implement business rules, authenticate users, integrate external services, and expose capabilities to client applications. In a full-stack project, the backend is not merely a collection of endpoints. It is an engineered system whose correctness, security, performance, maintainability, and operability determine the quality of the complete product. An API, or Application Programming Interface, is the controlled boundary through which software components communicate. API design therefore involves much more than choosing URL paths. It includes resource modelling, representations, validation, authentication, authorization, error semantics, versioning, documentation, observability, and governance. This chapter treats backend engineering as an architectural and professional practice. The examples use HTTP and JSON because they are common in web systems, but the underlying principles also apply to GraphQL, gRPC, event-driven systems, and internal service interfaces. Learning ObjectivesBy the end of this chapter, the learner should be able to: - Explain the responsibilities and architectural layers of a modern backend.
- Design resource-oriented HTTP APIs with coherent semantics.
- Apply validation, authentication, authorization, and secure error handling.
- Analyse consistency, transactions, performance, scalability, and reliability.
- Design a maintainable API contract and document it using an OpenAPI-style approach.
- Evaluate an API through testing, observability, governance, and ethical considerations.
1. Backend Engineering as a Systems DisciplineA backend commonly performs six related functions: - Transport handling: receives HTTP, gRPC, or messaging requests.
- Application orchestration: coordinates use cases and workflows.
- Domain logic: enforces business rules and invariants.
- Persistence: reads and writes databases, caches, and object stores.
- Integration: communicates with payment systems, identity providers, email services, and other APIs.
- Operations: provides logging, metrics, tracing, configuration, deployment, and recovery mechanisms.
A useful conceptual architecture separates these concerns into layers: | Layer | Main responsibility | Typical artefacts |
|---|
| Interface | Translate external requests and responses | Routes, controllers, serializers | | Application | Coordinate use cases | Services, commands, workflows | | Domain | Express business rules | Entities, value objects, policies | | Infrastructure | Implement technical dependencies | Repositories, database clients, queues | | Operations | Make the system observable and operable | Logs, metrics, traces, health checks |
Layering is not an absolute requirement. A small application may combine layers, while a large system may split them into services. The principle is to prevent transport details, database assumptions, and business rules from becoming inseparably coupled. Monoliths, modular monoliths, and microservicesA monolith is deployed as one application unit. It is often efficient for an early product because development, testing, deployment, and transactions are comparatively simple. A modular monolith retains one deployment unit but enforces strong internal module boundaries. This is frequently a better starting point than prematurely adopting microservices. Microservices divide a system into independently deployable services, usually aligned with business capabilities. They can improve team autonomy and independent scaling, but introduce network failure, distributed tracing, deployment coordination, data ownership problems, and eventual consistency. The correct architectural decision depends on organisational structure, domain boundaries, reliability requirements, and operational maturity—not on fashion. 2. Resource and Contract DesignAn API contract specifies what clients may send, what the server guarantees, and how failure is represented. A robust contract is explicit, stable, predictable, and documented. Resource-oriented modellingIn a REST-style API, URLs usually identify resources, while HTTP methods express operations: | Operation | Example | Typical status |
|---|
| Create | POST /orders | 201 Created | | Retrieve collection | GET /orders | 200 OK | | Retrieve item | GET /orders/{id} | 200 OK | | Replace item | PUT /orders/{id} | 200 OK or 204 No Content | | Partial update | PATCH /orders/{id} | 200 OK or 204 No Content | | Delete | DELETE /orders/{id} | 204 No Content |
The method must match the operation's semantics. GET should be safe: it should not intentionally change server state. PUT is generally idempotent, meaning repeating the same request has the same intended effect as performing it once. POST is commonly non-idempotent, although an application can provide idempotency keys to make selected operations safely repeatable. Resource names should normally be nouns rather than verbs. GET /customers/42/orders is generally more coherent than /getCustomerOrders. Hierarchical paths are useful when the relationship is meaningful, but excessive nesting can make resources difficult to access. A practical rule is to use nesting for ownership or strong contextual dependence and provide direct identifiers where independent access is needed. Representations and media typesA resource has a conceptual identity, while a representation is a transport format such as JSON. A representation should contain stable identifiers, relevant attributes, links or references where useful, and metadata such as timestamps. Dates should use an unambiguous standard such as ISO 8601, and monetary values should specify currency. Floating-point numbers should not be used casually for exact monetary calculations; integer minor units or decimal types are safer. For example: {
"id": "ord_8412",
"status": "confirmed",
"total": {"amount": 12500, "currency": "INR"},
"createdAt": "2025-02-14T10:30:00Z"
}The API should define whether unknown fields are ignored, rejected, or preserved. It should also distinguish omitted fields from fields explicitly set to null; these can have different meanings in updates. Status codes and errorsHTTP status codes communicate broad outcomes. Common choices include: 200 OK: successful retrieval or update with a response body.201 Created: successful creation, preferably with a Location header.202 Accepted: accepted for asynchronous processing.204 No Content: successful operation without a response body.400 Bad Request: malformed request or invalid syntax.401 Unauthorized: authentication is absent or invalid.403 Forbidden: identity is known but lacks permission.404 Not Found: resource does not exist or is intentionally concealed.409 Conflict: request conflicts with current state.422 Unprocessable Content: syntactically valid but semantically invalid input.429 Too Many Requests: rate limit exceeded.500 Internal Server Error: unexpected server failure.503 Service Unavailable: temporary inability to serve the request.
An error body should be machine-readable and safe. A useful structure includes a stable error code, human-readable message, request or correlation identifier, and field-level details where appropriate. Internal stack traces, SQL statements, access tokens, and personal data must not be exposed. 3. Validation, Business Rules, and TransactionsValidation occurs at several levels. Syntactic validation checks types, required fields, lengths, formats, and ranges. Semantic validation checks relationships, such as whether a delivery date is compatible with an order date. Authorization validation checks whether the caller may perform the operation. Domain validation protects invariants, such as preventing payment of an already cancelled order. Client-side validation improves usability, but the backend must always validate independently because clients are untrusted. Validation schemas should be reusable, versioned, and tested. Normalization—such as trimming whitespace or canonicalizing email addresses—should be deliberate because careless normalization can alter user data. A database transaction groups operations into an atomic unit. The classical ACID properties are: - Atomicity: all included changes succeed or none are committed.
- Consistency: constraints and invariants hold before and after the transaction.
- Isolation: concurrent transactions do not produce prohibited interference.
- Durability: committed changes survive the failures covered by the database's guarantees.
Transactions should be kept no longer than necessary. External network calls inside a database transaction can increase lock duration and create failure ambiguity. For workflows involving several systems, patterns such as an outbox, retry policy, compensating action, or saga may be more appropriate than one distributed transaction. Concurrency and idempotencyTwo requests may attempt to update the same resource simultaneously. Optimistic concurrency control addresses this by comparing a version number or entity tag. A client sends the version it last observed; the server rejects the update if the resource has changed. This prevents silent overwriting of another user's work. Idempotency keys are particularly important for payment or order creation. The server stores the key and the resulting outcome for an appropriate period. A repeated request with the same key should return the original result, while reuse of the key with materially different parameters should be rejected. 4. Authentication and AuthorizationAuthentication establishes identity; authorization determines permitted actions. Confusing the two causes serious security defects. A bearer token can identify a user, but it does not automatically grant access to every resource. Common authentication approaches include secure sessions, OAuth 2.0, and OpenID Connect. Session cookies should be protected with Secure, HttpOnly, and suitable SameSite attributes. Tokens should have limited lifetime and scope. Refresh tokens require careful storage, rotation, revocation, and monitoring. Authorization models include: - Role-based access control (RBAC): permissions are assigned to roles.
- Attribute-based access control (ABAC): decisions use attributes of users, resources, actions, and context.
- Relationship-based access control: permission depends on relationships such as owner, member, or administrator.
A mature system applies least privilege, denies by default, checks authorization on every protected operation, and avoids trusting identifiers supplied by clients. For example, accepting /users/17/profile is not sufficient evidence that the caller may view user 17. 5. Security EngineeringBackend security is a continuous risk-management process. Important controls include: - Use parameterized database queries or trusted query builders to reduce injection risk.
- Apply output encoding and content-security controls to reduce cross-site scripting consequences.
- Enforce request size, pagination, timeout, and rate limits.
- Store passwords using a modern adaptive password-hashing algorithm; never store plaintext passwords.
- Keep secrets in a managed secret store rather than source code or client bundles.
- Encrypt sensitive traffic in transit and protect sensitive data at rest where justified by risk.
- Log security events without logging passwords, tokens, or unnecessary personal data.
- Patch dependencies and generate a software bill of materials where organisational policy requires it.
- Use threat modelling to identify abuse cases before implementation.
Security testing should include unit tests for policy rules, integration tests for authentication boundaries, dependency scanning, static analysis, dynamic testing, and controlled penetration testing. No tool substitutes for sound design and human review. 6. Performance, Scalability, and ReliabilityPerformance is an end-to-end property. A useful decomposition of request latency is: Ttotal = Tqueue + Tnetwork + Tapplication + Tdatabase + Texternal Here, T_total is total response time, and the components represent queueing, network transfer, application processing, database work, and external-service calls. The equation is a simplified additive model; overlapping asynchronous work, retries, and client rendering may make real systems more complex. It is useful for identifying where time is spent, not for claiming that every request has perfectly separable components. Throughput describes completed work per unit time. If N requests complete during an observation interval of duration ∆t, average throughput is: X = N ÷ ∆t X is measured in requests per second when ∆t is measured in seconds. Average values can hide tail behaviour, so production systems should track percentile latency, especially p95 and p99. A service that averages 100 ms but has a p99 of 5 seconds may still provide a poor user experience.
Common performance techniques include appropriate database indexes, bounded queries, connection pooling, caching, pagination, batching, asynchronous processing, and avoiding N+1 query patterns. Caches require explicit decisions about freshness, invalidation, privacy, and failure behaviour. A cache must never allow one user's private response to be served to another user. Reliability involves graceful degradation, timeouts, bounded retries with backoff, circuit breakers, health checks, backups, disaster recovery, and tested restoration procedures. Retrying a non-idempotent operation without an idempotency strategy can create duplicate effects. 7. API Lifecycle and DocumentationAPI design is a lifecycle rather than a one-time activity: - Discover domain and consumer needs.
- Model resources, commands, data ownership, and policies.
- Write a contract before implementation where practical.
- Review the contract with frontend, backend, security, and product stakeholders.
- Implement and test against the contract.
- Publish documentation and examples.
- Monitor usage, errors, latency, and adoption.
- Deprecate deliberately and communicate breaking changes.
OpenAPI-style specifications can describe paths, parameters, schemas, security schemes, responses, and examples. Contract testing checks that the implementation conforms to the published interface. Consumer-driven contract testing is useful when independent teams depend on the same API. Versioning may be explicit in the URL, header, or media type. There is no universally correct strategy. A version should change when compatibility cannot be preserved, not merely whenever an internal implementation changes. Additive fields are often compatible, but clients must be designed to tolerate unknown fields. Removing fields, changing meanings, tightening accepted values, or changing authorization behaviour can be breaking changes. 8. Testing and ObservabilityA practical backend test strategy combines: - Unit tests: isolated domain and utility behaviour.
- Integration tests: interaction with databases, queues, and identity systems.
- Contract tests: agreement between API producers and consumers.
- End-to-end tests: critical workflows through realistic boundaries.
- Load and resilience tests: behaviour under volume and dependency failure.
- Security tests: abuse cases and access-control boundaries.
Testing should evaluate both successful and unsuccessful paths. A high code-coverage percentage does not prove that important business risks are covered. Observability combines logs, metrics, and traces. Logs should be structured and correlated with a request identifier. Metrics should include request count, error count, latency distributions, saturation, queue depth, and dependency health. Distributed traces reveal how a request travels through services. Operational dashboards should support decisions, not merely display large quantities of data. 9. Worked API Design ExampleConsider a university project-management platform. Students create projects, invite members, submit milestones, and receive review comments. A possible endpoint set is: | Need | Endpoint | Notes |
|---|
| List projects | GET /projects?status=active&page=1 | Filtered and paginated | | Create project | POST /projects | Requires authenticated student | | View project | GET /projects/{projectId} | Authorization checked | | Add member | POST /projects/{projectId}/members | Owner or coordinator only | | Submit milestone | POST /projects/{projectId}/milestones/{milestoneId}/submissions | Idempotency recommended | | Review submission | POST /submissions/{submissionId}/reviews | Reviewer permission required |
For a list endpoint, the contract should define the default page size, maximum page size, ordering, filtering syntax, and whether pagination is offset-based or cursor-based. Cursor pagination is often more stable for frequently changing collections, whereas offset pagination can be simpler for small administrative datasets. A create request might contain a title, description, and course identifier. The server validates fields, confirms that the student belongs to the course, creates the project and membership record in one transaction, and returns 201 Created. It should not accept ownerId from the client as authoritative; ownership derives from the authenticated principal. If a submission is reviewed twice, the domain policy must specify whether multiple reviews are allowed, whether a review replaces an earlier draft, and whether the operation is idempotent. This illustrates why endpoint syntax cannot replace domain analysis. 10. Applied Case: Illustrative Campus Marketplace APIBackgroundThe fictional CampusMarket platform allows students to list used books and devices, search listings, and arrange purchases through a university-approved payment provider. ProblemThe first implementation exposed database records directly, used unrestricted search queries, returned inconsistent errors, and accepted a client-supplied seller identifier. Users occasionally saw stale listings, while administrators lacked reliable audit records. AnalysisThe principal risks were insecure direct object references, weak ownership validation, excessive data exposure, unbounded queries, and unclear state transitions. The team modelled a listing lifecycle: draft → published → reserved → sold, with explicit cancellation transitions. The payment provider remained the source of truth for payment status, while CampusMarket owned listing and fulfilment status. Approach and solutionThe revised design introduced: POST /listings deriving the seller from the authenticated identity.GET /listings with bounded filters, cursor pagination, and public response schemas.PATCH /listings/{id} protected by ownership or administrator policy.- An idempotency key for purchase initiation.
- Optimistic version checks to prevent two buyers reserving the same listing.
- An outbox event for payment and notification processing.
- Structured audit events for publication, reservation, sale, and cancellation.
- Standard error objects that revealed no database details.
- Metrics for search latency, reservation conflicts, payment failures, and abandoned transactions.
OutcomeThe redesigned API reduced accidental data exposure, made state transitions testable, and clarified responsibility between the platform and payment provider. It also improved operational diagnosis because each purchase could be traced through request, reservation, payment, and notification events. Learning pointsThe case demonstrates that API quality depends on domain ownership, not just route naming. Secure identity derivation, explicit state machines, concurrency control, idempotency, and observability are mutually reinforcing design practices. 11. Ethical, Legal, and Governance ConsiderationsBackend systems often process identity, education, financial, or behavioural data. Engineers should collect only data necessary for a defined purpose, establish retention periods, restrict access, and provide appropriate transparency. Privacy requirements vary by jurisdiction, but principles such as purpose limitation, data minimization, access control, correction, deletion where applicable, and breach response are broadly important. Audit logs must themselves be protected because they can contain sensitive information. Automated decisions should be explainable to an appropriate degree, tested for discriminatory outcomes, and subject to human review when consequences are significant. AI-enabled backend features require additional controls for prompt or data leakage, model failure, unsafe outputs, provenance, monitoring, and fallback behaviour. An AI component does not remove the application's responsibility for authorization or correctness. Governance also includes API ownership, service-level objectives, change approval, dependency management, incident response, and deprecation policy. Technical debt should be recorded and prioritised by risk rather than ignored until failure occurs. 12. Contemporary Developments and Best PracticesCurrent backend practice increasingly includes platform engineering, infrastructure as code, managed cloud services, event streaming, serverless execution, and zero-trust security. These tools can improve delivery but also create new coupling and operational complexity. Teams should evaluate vendor lock-in, portability, cost visibility, cold-start behaviour, data residency, and incident responsibilities. Recommended practices are: - Start with domain boundaries and consumer needs.
- Prefer a modular monolith until independent deployment is justified.
- Treat the API contract as a product shared with consumers.
- Validate at the boundary and enforce rules in the domain.
- Make state transitions explicit.
- Design retries, timeouts, and idempotency together.
- Protect every object with an authorization decision.
- Measure tail latency and dependency health.
- Automate tests, documentation, deployment, and rollback.
- Review security, privacy, accessibility, and operational impact before release.
Chapter SummaryBackend engineering combines interface design, domain modelling, persistence, integration, security, operations, and governance. A high-quality API uses coherent resources, appropriate HTTP semantics, explicit representations, predictable status codes, and safe error structures. Validation must be enforced server-side, while authentication and authorization must remain conceptually distinct. Transactions protect local invariants; idempotency, optimistic concurrency, and outbox-style processing support reliable distributed workflows. Performance analysis benefits from latency decomposition, bounded queries, caching discipline, and percentile measurements. Documentation, contract testing, observability, versioning, privacy, and ethical governance are essential parts of the API lifecycle. The CampusMarket case illustrates how secure and maintainable design emerges from combining domain analysis with engineering controls. Key TermsBackend engineering: Design and operation of server-side software. API: A defined interface through which software components communicate. Resource: A conceptual object identified and manipulated through an API. Representation: A transport format of a resource, such as JSON. Idempotency: Property whereby repeating an operation has the same intended effect as performing it once. Authentication: Establishing the identity of a requester. Authorization: Determining what an authenticated requester may do. RBAC: Authorization based on assigned roles. ABAC: Authorization based on attributes and context. Transaction: A unit of work governed by atomicity and related guarantees. ACID: Atomicity, consistency, isolation, and durability properties. Optimistic concurrency: Conflict prevention using versions or entity tags. Pagination: Dividing a collection into bounded result sets. Rate limiting: Restricting request frequency or volume. Observability: Understanding system behaviour through logs, metrics, and traces. Contract testing: Testing conformance between an API implementation and its agreed interface. Circuit breaker: A reliability pattern that temporarily stops calls to a failing dependency. Outbox pattern: Persisting an event with a transaction before publishing it asynchronously. Technical debt: Future cost created by expedient or inadequate technical choices. Review QuestionsShort Answer Questions- Distinguish authentication from authorization.
- What is the purpose of an API contract?
- Define idempotency and give one backend example.
- State the four ACID properties.
- Why should backend APIs use bounded pagination?
Long Answer Questions- Explain the responsibilities of the interface, application, domain, and infrastructure layers.
- Compare a modular monolith with microservices, including benefits and risks.
- Discuss how validation, authorization, and domain invariants interact in a secure API.
- Explain API versioning, compatibility, documentation, and deprecation management.
- Analyse the role of logs, metrics, traces, and testing in backend operations.
Analytical / Application Questions- Design an API for submitting assignments, including resources, methods, status codes, authorization rules, and idempotency decisions.
- A payment request has a high duplicate rate after network timeouts. Analyse the failure mode and propose a reliable design.
- Two users attempt to purchase the same item simultaneously. Design a transaction and concurrency strategy that prevents inconsistent inventory state.
Multiple Choice Questions with AnswersQuestion 1Which HTTP method is generally intended to be idempotent when replacing a resource? A. POST B. PUT C. CONNECT D. TRACE Correct Answer: B. PUT Question 2A response of 403 most appropriately indicates that the requester is: A. Unauthenticated or missing credentials B. Authenticated but not permitted C. Sending malformed JSON D. Experiencing a server timeout Correct Answer: B. Authenticated but not permitted Question 3Which control prevents a client from silently overwriting a newer resource version? A. Optimistic concurrency control B. Response compression C. DNS caching D. Static rendering Correct Answer: A. Optimistic concurrency control Question 4What is the principal purpose of an idempotency key in payment initiation? A. To encrypt the payment amount B. To increase database storage capacity C. To prevent repeated requests from creating duplicate effects D. To replace authorization checks Correct Answer: C. To prevent repeated requests from creating duplicate effects Question 5Which property of ACID means that all operations in a transaction succeed or none are committed? A. Isolation B. Durability C. Consistency D. Atomicity Correct Answer: D. Atomicity Question 6Which approach is most appropriate for protecting against SQL injection? A. Parameterized queries B. Larger response payloads C. Disabling logs D. Using client-side validation only Correct Answer: A. Parameterized queries Question 7If 600 requests complete in 30 seconds, the average throughput is: A. 2 requests per second B. 20 requests per second C. 30 requests per second D. 600 requests per second Correct Answer: B. 20 requests per second Question 8Which observability signal is especially useful for following one request across multiple services? A. Distributed trace B. CSS stylesheet C. Database schema D. Static code comment Correct Answer: A. Distributed trace Question 9What is a major risk of placing a slow external network call inside a database transaction? A. Reduced source-code indentation B. Longer lock duration and ambiguous failure handling C. Automatic elimination of all retries D. Improved isolation without cost Correct Answer: B. Longer lock duration and ambiguous failure handling Question 10Which principle requires that users receive only the permissions necessary for their tasks? A. Least privilege B. Eventual consistency C. Content negotiation D. Horizontal partitioning Correct Answer: A. Least privilege
|