Foundations of Serverless Applications and Microservices

Chapter 5
APIs, Messaging, and Event-Driven Integration

Diploma in Cloud Computing
Foundations of Serverless Applications and Microservices   •   Diploma

APIs, Messaging, and Event-Driven Integration

Introduction and Context

Cloud applications rarely operate as isolated programs. A customer-facing application may call identity, payment, inventory, notification, analytics, and fulfilment services. In a microservices architecture, these capabilities are separated into independently deployable services. Serverless functions add another level of decomposition: a function may execute only when an HTTP request, queue message, timer, or event activates it.

Integration design determines whether such systems are responsive, reliable, secure, and maintainable. The central design decision is often whether communication should be synchronous, in which the caller waits for a response, or asynchronous, in which the sender continues while a broker or consumer processes a message later. REST, GraphQL, and RPC commonly support request–response interaction. Queues, publish-subscribe systems, event buses, and webhooks support asynchronous or event-driven interaction.

This chapter examines these mechanisms as engineering choices rather than isolated technologies. It focuses on service contracts, schemas, delivery guarantees, failure handling, API gateways, observability, and governance.

Learning Objectives

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

  1. Explain the roles of REST, GraphQL, and RPC in service integration.
  2. Distinguish synchronous calls from queues, publish-subscribe systems, event buses, and webhooks.
  3. Select an appropriate communication pattern for a cloud or serverless workload.
  4. Design API and event contracts using schemas, versioning, and compatibility rules.
  5. Apply retries, timeouts, idempotency, dead-letter handling, and correlation identifiers.
  6. Evaluate security, governance, observability, and operational limitations.

1. Communication Models

Synchronous request–response

A synchronous interaction follows this sequence:

  1. A client sends a request.
  2. The receiving service validates and processes it.
  3. The service returns a response or an error.
  4. The client waits, or times out, while processing occurs.

This model is useful when the caller needs an immediate result, such as retrieving a product, authenticating a user, or validating a payment. Its disadvantages include temporal coupling and cascading failure. If Service A waits for Service B, B must be available and sufficiently fast for A to complete.

A timeout is not proof that the operation failed. A request may have reached the server and completed after the client stopped waiting. Therefore, operations that can be retried should be designed to be idempotent: repeating the same request produces the same intended result as performing it once. For example, setting an account address is naturally more idempotent than charging a credit card.

Asynchronous communication

In asynchronous communication, a sender places a message or event into an intermediary or invokes a consumer without waiting for completion. The sender and receiver can operate at different speeds and may be temporarily unavailable. This improves resilience and allows workload buffering, but introduces eventual consistency, duplicate delivery, delayed failure detection, and more complicated monitoring.

A useful distinction is:

  • A command asks a particular service to perform an action: ReserveStock.
  • An event records that something has happened: OrderPlaced.
  • A message is the general envelope carrying a command, event, or data.

Commands generally have one intended owner. Events may have many independent consumers.

2. REST APIs

Representational State Transfer (REST) is an architectural style for networked systems. A REST API exposes resources through uniform HTTP semantics. Typical operations include:

HTTP methodCommon meaningTypical property
GETRetrieve a representationSafe and idempotent
POSTCreate or trigger processingUsually not idempotent by default
PUTReplace a resourceIdempotent when defined correctly
PATCHPartially modify a resourceDepends on operation design
DELETERemove a resourceUsually idempotent

A response should use meaningful status codes. For example, 200 OK indicates successful retrieval or update, 201 Created indicates successful creation, 202 Accepted indicates that processing was accepted but is incomplete, 400 Bad Request indicates invalid input, 401 Unauthorized indicates missing or invalid authentication, 403 Forbidden indicates insufficient permission, 404 Not Found indicates that a resource is unavailable, and 409 Conflict indicates a state conflict.

REST design should use nouns for resources, predictable representations, pagination for large collections, and explicit error bodies. A common error representation might contain a machine-readable code, a human-readable message, a correlation identifier, and field-level validation details.

REST is not simply “HTTP with JSON.” Its important ideas include resource identification, representations, stateless requests, a uniform interface, and cacheability where appropriate. In practice, many APIs use REST-inspired conventions without implementing every constraint strictly.

3. GraphQL and RPC

GraphQL

GraphQL exposes a typed schema through which clients request precisely the fields they need. A client may retrieve related data in one query rather than making several REST calls. This is useful for mobile applications and user interfaces with variable data requirements.

GraphQL commonly has queries for reads, mutations for state changes, and subscriptions for selected real-time updates. Its strengths include a discoverable schema, client-controlled projections, and reduced over-fetching. Its risks include expensive nested queries, complex authorization, caching difficulty, and denial-of-service through unbounded query depth or breadth. Production systems should apply query limits, cost analysis, pagination, authorization at field or object level, and persisted queries where appropriate.

RPC

Remote Procedure Call (RPC) presents communication as invoking a method on another service, such as GetUser or CalculateTax. Frameworks such as gRPC commonly use strongly typed interface definitions and efficient binary serialization. RPC is attractive for internal service-to-service communication requiring low latency and explicit contracts.

RPC can encourage overly fine-grained calls and may hide network failure behind a programming-language-like interface. Developers must remember that a remote call is not equivalent to a local function call: it has latency, serialization, authentication, partial failure, and versioning concerns.

CriterionRESTGraphQLRPC
Primary abstractionResourcesTyped data graphProcedures or methods
Client data selectionEndpoint-definedClient-selected fieldsMethod-defined
Common transportHTTPHTTPHTTP/2 or other transports
Strong typingOptional or schema-basedBuilt into schemaUsually built into interface
Typical usePublic APIs and broad integrationFlexible user interfacesInternal, low-latency services

4. API Gateways

An API gateway is an entry point between clients and backend services. It can provide routing, TLS termination, authentication integration, rate limiting, request transformation, caching, logging, and aggregation. In a serverless platform, the gateway often activates functions and applies authorization before invocation.

A gateway should not become a monolithic business-logic layer. Business rules belong in services or domain components, while cross-cutting concerns belong at the edge when doing so is safe. A gateway may also create a bottleneck or single operational dependency. It should therefore be deployed for high availability, monitored, and configured with explicit limits.

Typical gateway controls include:

  • authentication using tokens, mutual TLS, or signed requests;
  • authorization based on scopes, roles, or policies;
  • request-size, rate, and concurrency limits;
  • schema validation and content-type enforcement;
  • access logs and correlation identifiers;
  • protection against replay, injection, and abusive traffic.

5. Queues, Publish–Subscribe, and Event Buses

Message queues

A queue usually distributes work to one logical consumer or consumer group. A producer adds a message; a worker receives it and acknowledges successful processing. Queues are appropriate for order fulfilment, image conversion, report generation, and smoothing bursts of traffic.

Important queue properties include visibility timeout, retention period, maximum delivery attempts, ordering, and dead-letter handling. A worker should acknowledge a message only after the required side effects are durable. If a worker crashes before acknowledgement, the message may be delivered again. Consequently, consumers must tolerate duplicates.

Publish–subscribe

In publish–subscribe (pub/sub), a publisher sends an event to a topic. Multiple subscriptions can receive independent copies. This enables loose coupling: an OrderPlaced event can be consumed separately by billing, inventory, analytics, and notification services.

Pub/sub is appropriate when multiple consumers need the same fact. It also allows consumers to evolve independently. However, event ordering, subscription backlog, replay, retention, and consumer failure must be designed explicitly.

Event buses

An event bus routes events between producers and consumers, often using rules based on event type, source, subject, or attributes. It is particularly useful for integrating many services and responding to domain events. An event bus may route an event to functions, queues, workflows, or external systems.

A bus is not necessarily a durable database. Retention and replay capabilities vary. If audit or replay is important, the design may require an event log or durable stream in addition to routing.

Webhooks

A webhook is an HTTP callback sent by one system to another when an event occurs. It is useful for integrating SaaS platforms, payment providers, and partner systems. The receiver should authenticate signatures, validate timestamps, reject replays, respond quickly, and process the event asynchronously. A webhook endpoint should return an acknowledgement only after it has safely accepted the event, not necessarily after all business processing is complete.

6. Event-Driven Architecture

Event-driven architecture (EDA) organizes components around the production, routing, and consumption of events. It can be event notification, in which an event announces that something happened; event-carried state transfer, in which the event includes enough data for consumers to act; or event sourcing, in which an append-only event history is the primary record of state changes.

Event sourcing is more demanding than ordinary event notification. It requires durable ordering, replay procedures, projection rebuilding, schema evolution, and careful privacy management. It should not be adopted merely because a system uses events.

Event-driven systems often provide eventual consistency. If an order service commits an order and inventory updates shortly afterward, a temporary interval may exist in which the two views disagree. This is acceptable only when the business process defines how temporary inconsistency is handled.

A common coordination technique is the saga. A saga divides a distributed business transaction into local transactions. If a later step fails, compensating actions undo or offset earlier steps. A saga can be orchestrated by a coordinator or choreographed through events. Compensation is a business operation, not a literal database rollback: a dispatched item may need a refund rather than an impossible reversal.

Synchronous and asynchronous integration patterns Client Service request response Producer Queue / Topic Consumer A Consumer B message Synchronous versus asynchronous integration
Synchronous and asynchronous integration patterns
Figure: Synchronous and asynchronous integration patterns

Figure: A synchronous request–response path compared with asynchronous message distribution.

7. Schemas and Service Contracts

A service contract specifies how another party may communicate with a service. It includes operations, paths or methods, input and output schemas, authentication, error semantics, timing expectations, limits, and compatibility rules. OpenAPI is commonly used for HTTP APIs; GraphQL SDL describes GraphQL schemas; Protocol Buffers and similar interface-definition languages describe RPC contracts; JSON Schema can validate JSON messages.

A robust event envelope commonly includes:

FieldPurpose
eventIdGlobally unique event identifier
eventTypeSemantic type, such as OrderPlaced
occurredAtTime at which the event occurred
sourceProducing service or domain
subjectEntity to which the event relates
correlationIdIdentifier linking related operations
versionContract or event version
dataDomain-specific payload

Schema evolution must preserve compatibility. Adding an optional field is generally safer than renaming or removing a required field. Consumers should ignore unknown fields when feasible. Producers should avoid changing a field’s meaning while retaining its name. Breaking changes should use a new version, a migration strategy, or parallel support for old and new contracts.

Contract testing verifies that a provider and consumer agree. Consumer-driven contract tests are useful when many clients depend on one API, but they do not replace integration, security, performance, and failure testing.

8. Reliability Engineering for Integration

Distributed communication fails in ordinary ways: packets are lost, connections close, credentials expire, services overload, and dependencies return slow responses. Good designs make failure visible and bounded.

Timeouts prevent indefinite waiting. They should be based on a service-level objective and the end-to-end latency budget. Retries are appropriate for transient failures, not invalid requests or authorization failures. Exponential backoff with jitter reduces synchronized retry storms. A retry policy should specify the maximum attempts and total elapsed time.

A circuit breaker temporarily stops calls to an unhealthy dependency, allowing recovery and protecting callers. Bulkheads isolate resources so one workload cannot consume every thread, connection, or function concurrency slot. Rate limiting protects both providers and consumers.

A dead-letter queue stores messages that exceed delivery attempts or cannot be processed. It requires an operational process: alerting, inspection, correction, replay, and prevention of repeated failure. Poison messages should not circulate indefinitely.

Exactly-once processing is difficult to guarantee across independent systems. Practical designs usually aim for at-least-once delivery plus idempotent processing. A deduplication record may store a message identifier and processing result, but its storage and expiry must be designed consistently with the business operation.

For a simple queue, approximate backlog growth can be reasoned about using rates: if messages arrive at rate λ messages per second and workers successfully process at rate μ messages per second, sustained growth occurs when λ > μ. This observation is not a complete performance model because concurrency, batching, failures, and burstiness also matter; it is a basic capacity check.

9. Security, Governance, and Ethics

APIs and event channels are security boundaries. Apply least privilege to producers, consumers, operators, and service accounts. Encrypt traffic in transit and protect sensitive data at rest. Validate input at the boundary, but do not rely only on schema validation for authorization.

Important controls include token expiry, key rotation, signed webhooks, replay protection, tenant isolation, audit logs, secrets management, and network segmentation. Logs and events may contain personal or financial data. Data minimization, retention limits, access controls, masking, and deletion procedures are therefore essential. Event immutability can conflict with privacy obligations; systems should avoid placing unnecessary personal data in long-lived event histories.

Governance should define ownership for each API and event, supported versions, service-level objectives, data classifications, incident responsibilities, and deprecation timelines. An undocumented event is an undocumented dependency and becomes a source of operational risk.

10. Observability and Operations

Integration observability combines metrics, logs, and traces. Useful metrics include request rate, error rate, latency percentiles, queue depth, message age, retry count, dead-letter count, consumer lag, and webhook delivery success. A correlation identifier should travel through HTTP headers, message attributes, logs, and traces.

Distributed tracing helps show the path of a request across gateways, functions, queues, and services. However, traces can expose sensitive data and may be sampled. Observability must be designed with privacy and cost controls.

Operational runbooks should answer: What does an alert mean? Who owns the dependency? How can a failed message be inspected safely? Can it be replayed? Is replay idempotent? What is the customer impact? These questions distinguish production engineering from merely connecting endpoints.

Applied Case: Illustrative Order Processing Platform

Background

A fictional online retailer receives orders through a mobile application. It uses separate services for orders, payments, inventory, shipping, notifications, and analytics.

Problem

The first design used a synchronous chain: the mobile client called the order service, which called payment, inventory, shipping, and notification services before returning success. During traffic spikes, slow shipping calls caused timeouts. Customers retried, creating duplicate orders, while operators had little visibility into which step failed.

Analysis

Not every step requires an immediate result. The customer needs prompt confirmation that the order was accepted, but shipment creation and analytics can occur later. Payment authorization and initial inventory reservation are important business steps, yet they may be coordinated through a workflow rather than an unbounded HTTP chain.

Approach

The redesigned system uses an API gateway for authentication, rate limiting, and request validation. The order API creates an order with an idempotency key and returns 202 Accepted with an order identifier. It publishes OrderPlaced to an event bus. Payment and inventory consumers process the event independently, each using an idempotency record. A saga coordinator observes outcomes. If payment fails, the order becomes PaymentFailed; if inventory cannot be reserved, an authorized payment is voided or refunded according to the business policy. Notifications consume status events. Analytics receives its own subscription and does not block fulfilment.

The event envelope includes an event identifier, order identifier, event type, version, timestamp, source, and correlation identifier. Failed messages go to dead-letter queues. Dashboards show order-processing latency, consumer lag, and compensation failures.

Outcome

The customer-facing request is no longer held open by slow downstream services. Each component can scale independently, and failures are visible as business states rather than unexplained request timeouts. The design does introduce eventual consistency and requires operational procedures for replay and compensation.

Learning Points

The case illustrates that asynchronous design is not automatically superior. Immediate validation remains synchronous, while long-running or independently scalable work is asynchronous. Idempotency, explicit state transitions, contracts, and observability are necessary for the design to be dependable.

Contemporary Developments and Best Practices

Modern cloud platforms increasingly support managed API gateways, serverless queues, event buses, workflow orchestration, schema registries, and distributed tracing. Event-driven systems are also used with streaming platforms for high-volume telemetry and real-time analytics. AI services are commonly integrated through APIs and asynchronous job patterns; because model responses may be nondeterministic or costly, contracts should define input limits, timeout behaviour, audit requirements, and human review for high-impact decisions.

Recommended practices are:

  1. Choose communication style from business latency, consistency, and failure requirements.
  2. Treat remote calls as unreliable networks, not local functions.
  3. Define schemas, ownership, authentication, errors, and versioning before implementation.
  4. Make commands and consumers idempotent wherever duplicate delivery is possible.
  5. Use timeouts, bounded retries, backoff, circuit breakers, and dead-letter handling.
  6. Keep gateway responsibilities focused on cross-cutting concerns.
  7. Design events for useful autonomy without unnecessarily copying sensitive data.
  8. Instrument every hop with correlation and trace identifiers.
  9. Test contracts, security, load, failure recovery, and replay procedures.
  10. Document deprecation and incident-response processes.

Chapter Summary

APIs and messaging provide the communication foundation of microservices and serverless applications. REST offers resource-oriented HTTP integration; GraphQL provides client-selected access to a typed data graph; RPC offers strongly typed procedure-oriented communication. API gateways centralize edge concerns such as authentication, routing, validation, and rate limiting.

Queues buffer work for consumers, pub/sub distributes events to multiple subscribers, event buses route events according to rules, and webhooks connect external systems through callbacks. Event-driven architecture supports loose coupling but introduces eventual consistency, duplicate delivery, ordering concerns, and replay requirements. Service contracts and schemas make interactions explicit, while versioning protects consumers during evolution.

Reliable integration requires timeouts, carefully bounded retries, idempotency, dead-letter handling, circuit breakers, observability, and appropriate security. Sagas coordinate distributed business processes through local transactions and compensation. The appropriate design is determined by latency, consistency, ownership, failure, compliance, and operational requirements—not by technology fashion.

Key Terms

API: A defined interface through which software components communicate.

API gateway: An edge service that routes and governs API traffic.

Asynchronous communication: Interaction in which the sender does not wait for processing to finish.

Command: A message requesting a specific action.

Contract: The agreed interface, data, security, and behaviour between services.

Correlation identifier: An identifier linking related requests, messages, and operations.

Dead-letter queue: A destination for messages that cannot be processed successfully.

Event: A record that a significant fact or state change occurred.

Event bus: A routing mechanism for distributing events to consumers.

Eventual consistency: A model in which related representations become consistent after a delay.

GraphQL: A typed API query language and runtime allowing clients to select requested fields.

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

Message queue: A brokered store that buffers work for consumers.

Publish–subscribe: A pattern in which publishers send messages to topics and subscribers receive copies.

REST: An architectural style using resources, representations, and uniform web constraints.

RPC: A communication style that invokes operations on a remote service.

Saga: A distributed transaction pattern using local transactions and compensating actions.

Schema: A formal description of allowed data structure and types.

Webhook: An HTTP callback sent when an event occurs.

Review Questions

Short Answer Questions

  1. What is the main difference between synchronous and asynchronous communication?
  2. Why should a queue consumer be designed to tolerate duplicate messages?
  3. State two responsibilities commonly implemented by an API gateway.
  4. What is the purpose of a dead-letter queue?
  5. Define eventual consistency.

Long Answer Questions

  1. Compare REST, GraphQL, and RPC, including suitable use cases and limitations.
  2. Explain how schemas and versioning support reliable service contracts.
  3. Describe the roles of queues, pub/sub systems, and event buses in a microservices architecture.
  4. Explain how timeouts, retries, circuit breakers, and bulkheads reduce integration risk.
  5. Describe a saga and explain why compensation is not the same as a database rollback.

Analytical / Application Questions

  1. A payment service is slow and occasionally unavailable. Design a communication approach that protects the customer-facing API while preserving order processing. Justify your use of synchronous and asynchronous interactions.
  2. A webhook provider sends the same event three times and sometimes sends events out of order. Propose a receiver design that prevents harmful duplicate processing and manages ordering limitations.
  3. An organization wants to place full customer profiles in an immutable event stream for convenience. Evaluate the security, privacy, governance, and operational consequences, and recommend a safer alternative.

Multiple Choice Questions with Answers

Question 1

Which communication pattern allows a producer to continue without waiting for a consumer to finish processing?

A. Synchronous request–response

B. Asynchronous messaging

C. Local procedure call

D. Static file transfer

Correct Answer: B. Asynchronous messaging

Question 2

Which HTTP method is generally intended to retrieve a resource?

A. POST

B. PATCH

C. GET

D. DELETE

Correct Answer: C. GET

Question 3

What is a primary advantage of GraphQL for user interfaces?

A. It eliminates the need for authorization

B. Clients can request precisely the fields they need

C. It guarantees exactly-once delivery

D. It stores all data in one database

Correct Answer: B. Clients can request precisely the fields they need

Question 4

What is the main purpose of a dead-letter queue?

A. To permanently accelerate successful messages

B. To store messages that repeatedly fail processing

C. To replace authentication tokens

D. To cache GraphQL queries

Correct Answer: B. To store messages that repeatedly fail processing

Question 5

Which property is especially important when a message may be delivered more than once?

A. Idempotency

B. Compression

C. Encryption only at rest

D. Random routing

Correct Answer: A. Idempotency

Question 6

In a publish–subscribe system, what can happen to one published event?

A. Only the publisher can read it

B. It can be delivered to multiple independent subscribers

C. It must be processed synchronously by the publisher

D. It can never be retained

Correct Answer: B. It can be delivered to multiple independent subscribers

Question 7

Which field best links several related service operations for tracing?

A. Content-Type

B. Correlation identifier

C. HTTP method

D. Schema title

Correct Answer: B. Correlation identifier

Question 8

What does a saga use when a later distributed transaction step fails?

A. Compensating actions

B. A guaranteed global rollback

C. A larger API gateway

D. A new programming language

Correct Answer: A. Compensating actions

Question 9

Which change is generally safest for backward compatibility?

A. Removing a required field

B. Changing the meaning of an existing field

C. Adding an optional field

D. Changing an identifier type without notice

Correct Answer: C. Adding an optional field

Question 10

Why should webhook receivers often acknowledge quickly and process asynchronously?

A. To avoid validating the webhook

B. To reduce provider timeouts while preserving reliable acceptance

C. To guarantee events arrive in order

D. To remove the need for signatures

Correct Answer: B. To reduce provider timeouts while preserving reliable acceptance

Foundations of Serverless Applications and Microservices
Chapter 5 of 15