API Design and Microservices Architecture

Chapter 1
API and Distributed-Systems Foundations

Post Graduate Diploma in Full Stack Development
API Design and Microservices Architecture   •   Post Graduate

1. API and Distributed-Systems Foundations

Introduction and Context

Modern software rarely operates as a single isolated program. A mobile application retrieves data from remote services, an online retailer invokes payment and delivery systems, and an organisation may connect its customer, finance, analytics, and identity platforms through APIs. These interactions are enabled by distributed systems: collections of computing resources that cooperate across networks while appearing, from a user’s perspective, to provide a unified service.

This chapter establishes the conceptual foundation for API design and microservices architecture. It examines how clients and servers communicate, why distributed systems are difficult to design, and how architectural approaches such as service-oriented architecture, web services, microservices, monoliths, and cloud-native systems relate to one another. The central concern is not merely how to divide software into services, but how to evaluate the consequences of those divisions in terms of coupling, cohesion, latency, scalability, reliability, governance, and organisational responsibility.

An API is therefore understood as more than a collection of URLs. It is a deliberate boundary between software components, defining what one component may request, how it must request it, and what response or error it can expect. Good API design depends on sound distributed-systems reasoning.

Learning Objectives

By the end of this chapter, students should be able to:

1. Define API, client, server, protocol, endpoint, message, middleware, service, and related terminology.

2. Explain the client-server model and the principal constraints of distributed computing.

3. Distinguish monolithic, service-oriented, microservices, and cloud-native architectures.

4. Evaluate coupling and cohesion when establishing service boundaries.

5. Analyse the trade-offs among latency, scalability, availability, consistency, reliability, and operational complexity.

6. Apply architectural reasoning to realistic API and microservices scenarios.

7. Identify governance, security, ethical, and professional concerns in distributed applications.

APIs as Contracts Between Software Participants

An application programming interface is a defined means through which one software component interacts with another. The interface specifies available operations, input structures, output structures, rules of use, and failure behaviour. An API may be local, such as a programming-language library, or remote, such as an HTTP-based web API.

The word contract is important. An API contract establishes expectations between a provider and its consumers. A consumer should not need to know how a service stores data internally. Similarly, the provider should be able to improve its implementation without breaking consumers, provided that the contract remains compatible. This separation is an important form of abstraction.

Several terms are fundamental:

  • A client is a component that initiates a request for a resource or operation.
  • A server is a component that receives requests and provides resources or processing.
  • A request is a message sent by a client, usually containing an operation, target, metadata, and sometimes a payload.
  • A response is the server’s result, including status information, metadata, and possibly a payload.
  • An endpoint is a discoverable interaction point, commonly represented by a URI and an HTTP method.
  • A resource is an identifiable object or concept exposed through an API, such as an account, order, or product.
  • A protocol is a set of communication rules, such as HTTP, TCP, or messaging protocols.
  • A payload is the substantive data carried in a request or response.
  • Serialization converts an in-memory object into a transferable representation, such as JSON or XML; deserialization reverses the process.
  • A contract describes the structure and semantics that consumers and providers agree to follow.

A useful distinction exists between an API and an implementation. The API expresses what can be done and under what conditions; the implementation determines how it is done. For example, a product API may expose `GET /products/42`, while internally the product may be retrieved from a relational database, cache, or external catalogue.

APIs may be synchronous or asynchronous. In a synchronous interaction, the client waits for a response before proceeding. In an asynchronous interaction, the client submits a message or command and continues, receiving the result later through a callback, event, queue, or separate query. Synchronous APIs are often easier to understand, whereas asynchronous APIs can improve resilience and throughput for long-running or decoupled work.

The Client-Server Model

The client-server model separates responsibilities between requesters and providers. A browser, mobile application, or another service may act as a client. A server listens for requests, applies business rules, accesses resources, and returns a result. The roles are logical rather than permanent: a service can be a client when calling another service and a server when responding to its own consumers.

A typical interaction follows these stages:

1. The client identifies the target server, often through a domain name and name-resolution service.

2. A network connection is established, potentially using encryption such as TLS.

3. The client sends a request containing method, target, headers, authentication information, and payload where required.

4. The server validates the request, performs processing, and accesses internal resources.

5. The server returns a response with a status code, headers, and representation.

6. The client interprets the result and may retry, display information, or initiate another operation.

The model provides useful separation of concerns. Clients can evolve independently from servers, and servers can serve multiple client types. However, the separation introduces network dependence. A local function call may take microseconds and fail in relatively predictable ways; a remote call may experience delay, packet loss, congestion, authentication failure, partial execution, or an unavailable dependency.

HTTP APIs commonly use methods such as GET, POST, PUT, PATCH, and DELETE. A well-designed interface gives these operations clear semantics. GET generally retrieves data and should not modify server state. POST commonly creates a subordinate resource or initiates an operation. PUT traditionally replaces a resource and is expected to be idempotent: repeating the same request produces the same intended state. PATCH applies a partial modification, while DELETE requests removal. These conventions are design aids rather than substitutes for explicit documentation.

Why Distributed Systems Are Difficult

In a distributed system, components communicate through a network and do not share a single perfectly reliable clock, memory space, or failure domain. The following constraints shape architecture.

Partial failure

A component may fail while others continue operating. A payment service may be unavailable while an order service remains healthy. The calling service must decide whether to wait, retry, return a degraded response, or reject the operation. This differs from a simple single-process failure, where the whole application may stop together.

Variable latency

Network delay is not constant. A request may be fast under normal conditions and slow under congestion or load. Long chains of synchronous calls multiply this risk. If Service A calls B, which calls C, the user-visible response depends on the combined delays and failure probabilities of all three.

Uncertain completion

A client may time out even though the server has completed the operation. Retrying a non-idempotent request can therefore create duplicates, such as two payments or two orders. Idempotency keys, operation identifiers, and carefully designed state transitions help resolve this ambiguity.

Concurrency and consistency

Different replicas may temporarily contain different values. A user may update an address in one region while another request reads an older copy. Architects must choose suitable consistency guarantees rather than assuming that all nodes instantly agree.

Limited observability

A request crossing several services is difficult to diagnose without structured logs, metrics, traces, correlation identifiers, and health information. Operational visibility is not an optional add-on; it is part of the architecture.

Resource constraints and coordination

Bandwidth, CPU, memory, storage, and connection pools are finite. Distributed coordination can be expensive, especially when many services must agree before completing one business transaction.

The CAP theorem is often used as a conceptual guide: in the presence of a network partition, a distributed data system must make a trade-off between strong consistency and availability. The theorem does not mean that systems permanently choose only two properties in all circumstances. It highlights that partition tolerance is unavoidable in networked systems and that consistency and availability may conflict during partitions. Design decisions should therefore be expressed in business terms: which operations require immediate agreement, and which can tolerate temporary divergence?

Middleware: The Infrastructure Between Components

Middleware is software that mediates communication or common technical services between applications, operating systems, databases, and networks. It reduces the need for every application team to implement the same infrastructure concerns independently.

Examples include API gateways, message brokers, service registries, identity providers, workflow engines, object-relational mapping tools, and service meshes. Middleware may provide routing, authentication, authorization, protocol translation, serialization, rate limiting, retries, circuit breaking, transaction coordination, logging, and monitoring.

An API gateway is a client-facing entry point that can route requests to internal services, apply authentication and quotas, terminate TLS, transform messages, and aggregate responses. It simplifies external access but can become a bottleneck or an overly powerful central dependency if poorly governed.

A message broker enables producers and consumers to communicate indirectly through queues or topics. This temporal and spatial decoupling can improve resilience: a producer need not know whether a consumer is immediately available. The cost is more complicated delivery semantics, ordering, duplication handling, and monitoring.

A service mesh typically provides communication features through infrastructure proxies deployed alongside services. It can standardise traffic policies, mutual TLS, retries, telemetry, and service discovery. Nevertheless, it does not remove the need for sound application-level contracts or business error handling.

Middleware should be introduced to solve a recognised cross-cutting problem. Adding layers without understanding their operational and performance effects can obscure failures and make systems harder to operate.

From Monoliths to Services

A monolith is an application deployed as a single unit. Its modules may be internally well organised, but the runtime and release boundary is generally shared. Monoliths offer straightforward local calls, centralised testing, simple deployment, and relatively easy transactions. They become problematic when unrelated modules require independent scaling, when releases are tightly coupled, or when the codebase becomes difficult for teams to understand and change.

A modular monolith addresses some of these weaknesses by enforcing clear internal boundaries while retaining one deployable unit. This is often a strong starting point because it provides architectural discipline without immediately introducing network complexity.

Service-oriented architecture (SOA) organises capabilities as services that communicate through explicit contracts. SOA commonly emphasises enterprise integration, reuse, governance, and interoperability. Services may be relatively large and may share infrastructure or data platforms.

Web services are services made accessible through web technologies and standards. SOAP-based services use formal XML contracts and messaging conventions, while RESTful services use resource-oriented interactions and HTTP semantics. REST is an architectural style, not merely a synonym for JSON over HTTP. It emphasises constraints such as stateless interaction, uniform interfaces, and representation of resources.

Microservices are a style in which an application is composed of small, independently deployable services aligned with business capabilities. Each service generally owns a focused responsibility, has an explicit interface, and can be developed and deployed by an autonomous team. The term small is contextual: a service should be no smaller than necessary for meaningful ownership and no larger than a boundary that prevents independent change.

Microservices are not simply a set of small classes or separate processes. They imply organisational, operational, and data-management consequences. Teams must manage deployment automation, observability, service discovery, version compatibility, distributed security, failure recovery, and often independent data ownership.

Architectural Evaluation: Coupling, Cohesion, and Trade-offs

Cohesion describes how closely the responsibilities within a module or service belong together. High cohesion means that a service focuses on a meaningful capability, such as inventory reservation or identity management. Low cohesion produces a service that contains unrelated responsibilities and becomes difficult to understand.

Coupling describes the degree of dependency between components. Tight coupling may occur when services share private databases, depend on internal implementation details, require simultaneous releases, or create long synchronous call chains. Loose coupling allows independent evolution, but it may require more explicit contracts, eventual consistency, and coordination mechanisms.

The design objective is not zero coupling. A business process necessarily contains relationships. The objective is appropriate coupling: dependencies should be explicit, stable, and aligned with genuine business relationships. A service that owns customer data should not expose its database tables merely because another service finds direct access convenient.

Several trade-offs must be assessed together:

  • Latency versus independence: Separate services may be independently deployed, but remote calls add network delay.
  • Scalability versus consistency: Independent scaling and replicated data may improve throughput while making immediate consistency harder.
  • Resilience versus complexity: Queues, retries, and fallbacks can prevent cascading failure but introduce duplicate messages, delayed results, and more complex diagnosis.
  • Autonomy versus governance: Teams can move quickly with service ownership, but common standards are needed for security, observability, and compatibility.
  • Isolation versus transaction simplicity: Separate data ownership reduces coupling, but cross-service transactions may require sagas or compensating actions.
  • Reuse versus changeability: A shared service can avoid duplication, yet excessive reuse creates a central dependency that slows evolution.

Scalability also has multiple meanings. Vertical scaling increases the resources of one instance. Horizontal scaling adds instances. A stateless service is generally easier to scale horizontally because any instance can handle a request. Stateful components require session replication, partitioning, or external state stores. Scalability must be evaluated against workload characteristics, cost, operational skill, and performance objectives rather than assumed from the use of microservices.

Cloud-Native Architecture

Cloud-native architecture uses automation, elastic infrastructure, managed services, containerisation where appropriate, declarative configuration, and operational practices designed for change and failure. It is not synonymous with placing an old monolith on a cloud virtual machine.

Common cloud-native characteristics include independently deployable components, immutable or reproducible deployments, automated testing and delivery, infrastructure as code, centralised observability, elastic scaling, and explicit treatment of failure. Containers can package applications consistently, while orchestration platforms can schedule workloads, expose services, perform health checks, and replace failed instances.

However, cloud-native systems may increase dependence on platform providers, create complex cost structures, and require specialised operational capabilities. Managed databases, queues, identity systems, and monitoring platforms improve productivity but create governance and portability considerations. Architecture should therefore be driven by business and technical requirements rather than by fashionable terminology.

Designing for Failure and Responsible Operation

A professional API design anticipates failure. Timeouts should be finite and appropriate to the operation. Retries should be limited, use backoff, and occur only when repetition is safe. Circuit breakers can stop calls to an unhealthy dependency and allow recovery. Bulkheads isolate resource pools so that one failing dependency does not consume all available threads or connections. Fallbacks should return truthful degraded behaviour rather than silently inventing data.

Security is part of the API contract. Authentication establishes identity; authorization determines permitted actions. Sensitive data should be minimised, encrypted in transit and at rest where appropriate, and excluded from logs unless strictly necessary. Rate limits protect availability and reduce abuse. Input validation, output encoding, dependency management, audit trails, and secure secret storage are essential professional practices.

Governance includes API ownership, documentation, versioning, change review, deprecation policies, service-level objectives, data retention, and compliance. Privacy regulations may impose requirements concerning consent, purpose limitation, access, correction, retention, and cross-border transfer. Ethical design also requires considering accessibility, discriminatory outcomes, surveillance risks, and the consequences of service unavailability for vulnerable users.

An Illustrative Case: Decomposing an Online Retail Platform

Background

A fictional retailer, Northstar Retail, operates a successful online store. Its original application is a modular monolith containing catalogue, shopping cart, orders, payments, inventory, and customer accounts. The application is deployed weekly as one unit.

Situation and Problem

During seasonal campaigns, catalogue browsing creates heavy load and slows checkout. A minor change to delivery rules requires the entire application to be tested and deployed. The technology team proposes converting every module into a microservice immediately. Business leaders, however, are concerned about payment errors, operational cost, and customer impact.

Analysis

The existing application has some internal cohesion, but catalogue reads and checkout transactions have different scaling and reliability needs. The modules also share a database, which means that physical separation would create data ownership and consistency challenges. A direct extraction of all modules would introduce network calls without first clarifying contracts.

The team maps business capabilities and identifies coupling. Catalogue and search can tolerate slightly stale data and require high read scalability. Payment requires strong security, careful idempotency, and auditable state transitions. Inventory must avoid overselling but can use a reservation model rather than a distributed two-phase transaction.

Approach

Northstar first strengthens the modular boundaries within the monolith and introduces contract tests. It places a cache and read-optimised search index in front of catalogue queries. It then extracts catalogue as an independently deployable service because its workload and release cadence differ significantly. The service owns its catalogue representation and publishes product-change events.

Payment is extracted later, with an explicit API, idempotency keys, timeouts, audit logging, and a reconciliation process. Order processing uses a saga-like workflow: an order is created, inventory is reserved, payment is authorised, and the order is confirmed. If payment fails after inventory reservation, a compensating action releases the reservation. The system does not pretend that all steps occur in one atomic database transaction.

An API gateway provides external routing and authentication, while distributed tracing links a customer request across services. The team defines service-level objectives for checkout latency and availability, and uses load tests before migration.

Outcome

Catalogue traffic can scale independently, and catalogue deployments no longer require checkout deployment. Checkout remains more carefully governed because it contains high-value state transitions. The retailer accepts some eventual consistency in product search but maintains stronger guarantees for payment status and order confirmation.

Learning Points

The case demonstrates that decomposition should follow business capability, cohesion, and change patterns rather than an arbitrary service count. A modular monolith may be a useful intermediate architecture. Independent services require explicit data ownership, observability, failure handling, security, and organisational accountability. The most appropriate architecture is a context-dependent trade-off, not a universal prescription.

Common Mistakes and Limitations

A frequent mistake is treating microservices as a guaranteed solution to poor code quality or slow delivery. Distributed deployment cannot compensate for unclear requirements, weak testing, or ineffective team ownership. Another mistake is creating shared databases that allow services to bypass each other’s contracts. This produces distributed code with centralised coupling.

Other risks include excessive synchronous chaining, indiscriminate retries, chatty APIs, incompatible schema changes, insufficient capacity planning, and monitoring based only on server availability rather than business outcomes. Teams may also underestimate data migration, local development, incident response, and the cost of running many independently deployed components.

Versioning requires discipline. Backward-compatible additions are generally safer than changing meanings or removing fields. Consumers should be given a deprecation period, and contracts should be tested in realistic integration environments. Documentation should explain semantics, security requirements, errors, limits, and examples rather than only listing endpoints.

Current Developments and Best Practices

Contemporary API platforms increasingly use machine-readable specifications, automated contract testing, schema registries, platform engineering, and policy-as-code. Event-driven architectures are common for integration and asynchronous workflows. Zero-trust security models assume that network location alone does not establish trust. OpenTelemetry-style instrumentation supports common traces, metrics, and logs across heterogeneous services. AI-assisted development can generate API scaffolding, tests, and documentation, but generated code still requires human review for security, privacy, correctness, and business semantics.

Effective practice includes the following principles:

  • Begin with business capabilities and user outcomes, not technology labels.
  • Prefer high cohesion and explicit, stable contracts.
  • Keep service boundaries understandable and assign clear ownership.
  • Use synchronous calls for short, immediate interactions and asynchronous messaging for decoupled or long-running work.
  • Design idempotency, timeouts, retries, authentication, authorization, and observability from the beginning.
  • Treat data ownership and consistency as architectural decisions.
  • Automate testing, deployment, configuration, and rollback.
  • Measure latency, error rate, saturation, availability, and business success rather than relying on intuition.
  • Introduce microservices incrementally and retain a modular monolith when it better fits the context.

Chapter Summary

APIs are contracts that enable software components to communicate while hiding implementation details. The client-server model provides separation of responsibilities but introduces network-dependent failure, latency, and consistency concerns. Distributed systems must account for partial failure, uncertain completion, concurrency, limited observability, and finite resources.

Middleware provides shared communication and operational capabilities, including routing, messaging, security, and telemetry. Monoliths, modular monoliths, SOA, web services, microservices, and cloud-native architectures represent different ways of organising software and operations. Microservices are most effective when boundaries exhibit high cohesion, coupling is explicit and manageable, and teams can support the necessary deployment and operational practices.

Architectural decisions involve trade-offs among scalability, latency, consistency, availability, resilience, autonomy, cost, and governance. Responsible API design includes security, privacy, versioning, observability, failure handling, and ethical consideration. The Northstar case illustrates that incremental decomposition based on business capability is generally more defensible than indiscriminate conversion to microservices.

Key Terms

API: A defined interface through which software components exchange operations or data.

Client: A component that initiates a request for a resource or service.

Server: A component that receives requests and provides processing or resources.

Endpoint: A specific interaction point, usually identified by a URI and operation.

Protocol: A set of rules governing communication between components.

Payload: The substantive data carried in a request or response.

Serialization: Conversion of data into a transferable representation.

Middleware: Software that mediates communication and supplies shared technical capabilities.

API gateway: An entry point that routes, secures, and sometimes transforms API traffic.

Message broker: Infrastructure that stores and routes messages between producers and consumers.

Monolith: An application generally built and deployed as one unit.

Modular monolith: A single deployable application with explicit internal module boundaries.

SOA: An architectural approach that organises capabilities as contract-based services, often for enterprise integration.

Microservices: Independently deployable services aligned with focused business capabilities.

Cohesion: The degree to which responsibilities within a component belong together.

Coupling: The degree of dependency between components.

Idempotency: A property whereby repeating an operation has the same intended effect as performing it once.

Eventual consistency: A model in which replicas may temporarily differ but converge over time.

Observability: The ability to understand internal system behaviour through outputs such as logs, metrics, and traces.

Cloud-native architecture: An approach using automation, elasticity, managed infrastructure, and design for distributed operation and failure.

Review Questions

Short Answer Questions

1. What is meant by an API contract?

2. Distinguish authentication from authorization.

3. Why is partial failure a central concern in distributed systems?

4. Define cohesion and coupling.

5. What is the purpose of an API gateway?

Long Answer Questions

1. Explain the client-server model and analyse the problems introduced when communication crosses a network.

2. Compare a monolith, modular monolith, SOA, and microservices architecture.

3. Discuss how latency, consistency, availability, and scalability influence distributed-system design.

4. Explain the roles of middleware, message brokers, and service meshes.

5. Describe the design and operational practices required for a reliable microservices system.

Analytical / Application Questions

1. A team proposes splitting a tightly coupled application into fifteen services, all sharing one database. Evaluate the proposal and recommend a more suitable approach.

2. An order API times out after submitting a payment request, and the client retries automatically. Analyse the risks and design safeguards.

3. A product-search service can tolerate stale results, but payment status cannot be stale. Propose suitable communication, consistency, and failure-handling strategies for both capabilities.

22. Multiple Choice Questions with Answers

Question 1

Which statement best describes an API contract?

A. The internal database schema used by a service

B. An agreement defining operations, data, and expected behaviour between software components

C. A network cable connecting two servers

D. A deployment script for installing an application

Correct Answer: B. An agreement defining operations, data, and expected behaviour between software components

Question 2

Why can a remote service call not be treated exactly like a local function call?

A. Remote calls always return incorrect data

B. Remote calls cannot use structured data

C. Remote calls introduce variable latency and partial failure

D. Remote calls never support authentication

Correct Answer: C. Remote calls introduce variable latency and partial failure

Question 3

Which design most directly improves safety when a client may retry a request after a timeout?

A. Making the operation idempotent or using an idempotency key

B. Removing all response status codes

C. Increasing the number of synchronous dependencies

D. Writing private database tables into the response

Correct Answer: A. Making the operation idempotent or using an idempotency key

Question 4

A service containing catalogue search, payroll, and customer notification responsibilities most clearly demonstrates low:

A. Availability

B. Cohesion

C. Encryption

D. Idempotency

Correct Answer: B. Cohesion

Question 5

What is a principal risk of excessive synchronous calls across microservices?

A. The system becomes independent of networks

B. Latency and failures can propagate through the call chain

C. Data ownership becomes automatically clearer

D. Observability is no longer necessary

Correct Answer: B. Latency and failures can propagate through the call chain

Question 6

Which statement best distinguishes a modular monolith from a microservices architecture?

A. A modular monolith has no internal boundaries

B. A modular monolith is usually one deployable unit despite having explicit modules

C. Microservices must always share one database

D. Microservices cannot communicate through messages

Correct Answer: B. A modular monolith is usually one deployable unit despite having explicit modules

Question 7

A message broker primarily supports which form of decoupling?

A. It allows producers and consumers to communicate without requiring simultaneous availability

B. It guarantees that every message is processed exactly once in all conditions

C. It removes the need for data governance

D. It converts every service into a monolith

Correct Answer: A. It allows producers and consumers to communicate without requiring simultaneous availability

Question 8

In the Northstar case, why was catalogue functionality extracted before all other modules?

A. It required stronger payment guarantees than checkout

B. It had different workload and scaling characteristics and could tolerate some stale data

C. It had no business ownership

D. It needed to share private tables with payment

Correct Answer: B. It had different workload and scaling characteristics and could tolerate some stale data

Question 9

What does observability provide in a distributed system?

A. A guarantee that failures cannot occur

B. The ability to infer system behaviour from logs, metrics, and traces

C. A replacement for authentication

D. A method of eliminating all network latency

Correct Answer: B. The ability to infer system behaviour from logs, metrics, and traces

Question 10

Which architectural decision best reflects appropriate coupling?

A. Every service directly edits every other service’s database

B. Services share private implementation details to reduce documentation

C. Services expose explicit, stable contracts and retain clear data ownership

D. All services must be released together

Correct Answer: C. Services expose explicit, stable contracts and retain clear data ownership

API Design and Microservices Architecture
Chapter 1 of 15