Foundations of Serverless Applications and Microservices

Chapter 15
Professional Cloud-Native Application Project

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

Professional Cloud-Native Application Project

Introduction and Context

A cloud-native application is designed to exploit the capabilities of cloud platforms rather than merely being hosted on remote servers. Typical characteristics include automated provisioning, elastic scaling, managed services, observability, resilient communication, secure identity management, and frequent, low-risk delivery. Serverless functions and microservices are two important implementation approaches, but neither is a complete architecture by itself. A professional solution must connect business requirements to architecture, code, security controls, deployment processes, operational measurements, and evidence of quality.

This chapter presents an end-to-end method for developing a small production-oriented solution. The emphasis is not on a particular vendor. AWS Lambda, Azure Functions, Google Cloud Functions, container platforms, managed databases, queues, and API gateways provide alternative implementations of the same architectural ideas.

A useful project boundary is a small order-processing system. Customers submit orders through an API. The system validates the order, records it, requests payment authorisation, and publishes an event for notification. This example is sufficiently realistic to demonstrate service boundaries, asynchronous communication, failure handling, security, deployment, and monitoring without requiring a large enterprise platform.

Learning Objectives

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

  1. Translate business and technical requirements into a feasible cloud-native architecture.
  2. Select appropriate boundaries for serverless functions and microservices.
  3. Design synchronous APIs and asynchronous event flows.
  4. Apply security, reliability, and data-management principles.
  5. Implement infrastructure and application delivery using repeatable automation.
  6. Define useful service-level indicators and interpret operational evidence.
  7. Document, test, deploy, and evaluate a production-oriented solution.
  8. Identify limitations, ethical responsibilities, and opportunities for improvement.

From Requirements to an Architectural Decision

Professional engineering begins with requirements rather than technology selection. Functional requirements state what the system must do; non-functional requirements describe qualities such as performance, availability, security, maintainability, and cost.

For the illustrative order system, functional requirements might include:

  • A customer can submit an order containing one or more products.
  • The system rejects invalid product identifiers, quantities, or prices.
  • A valid order receives a unique identifier and an initial status.
  • Payment authorisation is requested without exposing card details to application code.
  • Customers receive a notification when processing succeeds or fails.

Possible non-functional requirements are:

  • 95% of order-submission requests should complete within 800 ms, excluding external payment processing.
  • The API should be available during normal business hours with an agreed recovery procedure.
  • Duplicate client submissions must not create duplicate orders.
  • Personal data must be encrypted in transit and at rest.
  • A small team should be able to operate the system with limited infrastructure administration.

Requirements should be measurable where possible. A service-level indicator (SLI) is an observed measurement, such as successful requests divided by total valid requests. A service-level objective (SLO) is a target for that measurement, such as 99.5% successful requests over a calendar month. A service-level agreement (SLA) is a formal commitment, often including remedies or contractual consequences. These terms should not be treated as interchangeable.

A decision record should explain why a technology was selected. Serverless functions are attractive when workloads are event-driven, variable, and relatively short-lived. They reduce server administration but introduce platform limits, cold-start variation, execution time limits, vendor dependence, and more complicated distributed tracing. Microservices can support independent ownership and deployment, but excessive decomposition increases network calls, operational overhead, and data-consistency challenges.

The correct question is therefore not “Should every component be a function?” but “Which responsibility benefits from independent scaling, deployment, security, or failure isolation?” A modular monolith may be a better starting point when the domain is small and the team is inexperienced.

A Reference Architecture

The illustrative design contains the following components:

ComponentResponsibilityCommunication
API gatewayHTTPS endpoint, routing, throttling, authentication integrationSynchronous HTTP
Order serviceValidate commands and create order recordsHTTP and database
Order databaseStore order state and idempotency recordsManaged database protocol
Payment adapterCall a payment provider without storing card dataQueue or controlled HTTP
Event bus or queueBuffer work and decouple producers from consumersAsynchronous messages
Notification serviceSend email or other customer notificationEvent consumer
Monitoring platformLogs, metrics, traces, alarms, audit recordsTelemetry protocols
Identity providerIssue and validate tokens and rolesOAuth 2.0/OpenID Connect or equivalent

The API gateway authenticates the request or delegates authentication to an identity provider. The order service validates the command and writes an order with status PENDING. It then publishes an OrderSubmitted event or places a message on a queue. A payment component consumes the message and updates the order to AUTHORISED or PAYMENT_FAILED. A notification component consumes state-change events.

Synchronous calls are useful when the caller needs an immediate result, such as validation or creation of an order identifier. Asynchronous messages are useful when work may be slow, temporarily unavailable, or independently scalable. Queues also provide buffering, but they do not eliminate failure. Messages may be delayed, duplicated, rejected, or delivered out of order. Consumers must therefore be idempotent and should use retry limits and a dead-letter queue.

A message commonly includes an event identifier, event type, occurrence time, aggregate identifier, schema version, and relevant data. Consumers should not rely on undocumented fields. Schema evolution should be compatible: adding an optional field is generally safer than renaming or removing a required field.

Domain Boundaries and Data Ownership

A service boundary should represent a coherent business capability. The order service owns order status and order rules; the payment adapter owns communication with the payment provider; the notification service owns delivery attempts. Each service should have a clear owner for its data. Sharing one database schema across all services may appear convenient, but it creates hidden coupling and makes independent deployment difficult.

Separate data stores do not imply perfect isolation. A business transaction may cross several services. Instead of requiring a distributed transaction, a cloud-native design often uses a saga: a sequence of local transactions connected by events. If payment fails after an order is created, the order service performs a compensating state transition to PAYMENT_FAILED. A compensation is not necessarily a literal reversal; its meaning depends on the business domain.

Consistency must be stated explicitly. An order may be immediately consistent within the order service while the notification view becomes consistent a few seconds later. Users should receive honest status information rather than an appearance of instantaneous global consistency.

Implementation Practices

A professional project should use a repository with a predictable structure, for example:

project/
  services/order/
  services/payment-adapter/
  services/notification/
  infrastructure/
  contracts/
  tests/
  docs/
  .github-or-ci/

Configuration that differs between environments should be externalised. Secrets must be stored in a managed secret store or protected CI/CD variable system, not committed to source control. Configuration should identify the environment, region, database endpoint, queue name, and logging level without embedding credentials.

Input validation must occur at the system boundary. The service should validate data types, required fields, maximum lengths, allowed ranges, and business rules. Validation is not a substitute for authorisation: a correctly formed request can still be forbidden. The server must calculate or verify prices rather than trusting a client-supplied total.

Idempotency is essential for retried requests. A client supplies an idempotency key, and the order service stores the key with the resulting response or order identifier. A repeated request with the same key returns the original result instead of creating another order. The key should be associated with the authenticated client and should have a defined retention period.

A function should generally perform one coherent responsibility, use timeouts on external calls, and avoid unnecessary startup work. Connections to databases and providers should be reused where the platform permits, but code must not assume that memory or a process will persist between invocations. Long-running work should be moved to a queue or workflow service rather than hidden inside a request handler.

Security and Governance

Security is a system property, not a final testing stage. The design should apply least privilege: each function receives only the permissions required for its task. The order service should not have permission to read payment-provider secrets unless necessary, and the notification service should not be able to modify arbitrary order records.

Important controls include:

  • TLS for network communication and encryption at rest for databases, queues, and logs.
  • Strong authentication for users and workload identities.
  • Authorisation based on roles, scopes, or resource ownership.
  • Validation, rate limiting, and protection against injection and abusive traffic.
  • Secret rotation and avoidance of sensitive values in logs.
  • Centralised audit records for administrative and security-relevant actions.
  • Dependency scanning, code review, and vulnerability remediation.
  • Backup, restoration, and retention policies.

Payment card data should be handled by a compliant payment provider using tokenisation or hosted payment interfaces. The application should store a provider token and transaction reference rather than raw card details. Personal data requires purpose limitation, data minimisation, controlled retention, and appropriate access. The exact legal obligations depend on jurisdiction and sector; technical teams should consult institutional or legal guidance for frameworks such as the GDPR, PCI DSS, or applicable national privacy law.

Logs must support diagnosis without becoming a data-leak channel. A log event should include a timestamp, service name, severity, correlation identifier, and useful operation context. It should not include passwords, access tokens, full payment details, or unnecessary personal information.

Testing Strategy

Testing should be layered. Unit tests verify rules inside a function or module. Contract tests verify that a producer and consumer agree on an API or event schema. Integration tests exercise managed-service boundaries using suitable test resources. End-to-end tests verify an important business journey. Security tests examine authentication, authorisation, dependency risk, and common input attacks.

A practical pipeline is:

  1. Format and lint the code.
  2. Run unit and contract tests.
  3. Scan dependencies and infrastructure definitions.
  4. Build an immutable artifact.
  5. Deploy to a test environment.
  6. Run integration and smoke tests.
  7. Obtain an approval appropriate to the risk.
  8. Deploy progressively and monitor.

Tests should include failure cases: duplicate messages, provider timeouts, malformed events, expired tokens, unavailable databases, and notification retries. A successful test suite does not prove that the system is reliable; it provides evidence about specified behaviours.

Infrastructure and Deployment

Infrastructure as Code (IaC) expresses resources such as functions, permissions, queues, databases, alarms, and API routes in version-controlled definitions. IaC improves repeatability and reviewability, but it must itself be tested and secured. State files may contain sensitive information and require protected storage.

A deployment artifact should be immutable, identified by a version or commit reference, and promotable between environments. Environment-specific values should be injected through controlled configuration rather than by rebuilding different source code for each environment.

Blue-green deployment maintains two environments and switches traffic between them. Canary deployment sends a small proportion of traffic to the new version before increasing exposure. Rolling deployment replaces instances or function versions gradually. Serverless platforms may provide aliases, versions, traffic weights, or similar mechanisms. The choice depends on platform capability and rollback requirements.

Rollback should be rehearsed. Application rollback may not reverse a database migration, so database changes should normally be backward-compatible: add a new field before using it, migrate data, then remove obsolete structures only after all consumers have moved.

Observability and Evaluation

Observability combines logs, metrics, traces, and contextual metadata. Metrics should distinguish symptoms from causes. Useful indicators include request success rate, latency percentiles, queue age, retry count, dead-letter messages, function errors, database throttling, and cost by service.

The arithmetic mean latency is:

x̄ = (1/n) ∑ᵢ₌₁ⁿ xᵢ

where xᵢ is the latency of request i, n is the number of observations, and x̄ is measured in the same time unit as each xᵢ. The mean is useful for an overall average but can hide slow outliers. Percentiles, such as p95 or p99, are often more informative for user experience. A p95 latency of 800 ms means that approximately 95% of observed requests are at or below 800 ms; it does not mean that every request completes within 800 ms.

For a period with S successful valid requests and T total valid requests, an availability-style success ratio is:

Success ratio = S ÷ T

The ratio has no unit and is commonly expressed as a percentage. It is meaningful only when the measurement scope, exclusions, time window, and definition of success are documented. If 9,950 of 10,000 valid requests succeed, the ratio is 0.995, or 99.5%.

Distributed tracing should propagate a correlation or trace identifier across gateway, functions, queues, and external calls. Alerting should be tied to user impact or imminent risk rather than every unusual log line. Runbooks should explain what an alert means, how to investigate it, and when to escalate.

Cost evaluation should include invocation charges, execution duration, data transfer, storage, managed databases, observability, and third-party services. The cheapest design is not necessarily the most economical if it causes outages or excessive maintenance. A simple cost model can compare alternatives, but provider pricing changes and usage assumptions must be recorded.

Illustrative Case: Campus Equipment Ordering Platform

Background

A college wants a platform through which departments can request laptops and laboratory equipment. The existing email process causes duplicate requests, weak visibility, and delayed approval. The project team has two developers and an operations technician.

Problem Analysis

The team identifies three capabilities: order submission, payment or budget authorisation, and notification. It rejects a separate service for every database table because the team cannot operate that complexity. The first release uses an order service, a payment-adapter function, and a notification function connected through a queue. A managed identity service protects the API, and a managed database stores order state.

Approach

The order endpoint accepts a request containing product identifiers and quantities. It obtains current product information from an authorised catalogue interface rather than trusting client prices. It validates the requester’s department and writes a PENDING order with an idempotency key. It publishes an OrderSubmitted message containing a schema version and trace identifier.

The payment adapter consumes the message, calls the external authorisation service with a timeout, and records the provider reference. Transient failures are retried with bounded backoff. A message that exceeds the retry limit enters a dead-letter queue. The notification function consumes OrderAuthorised and OrderFailed events and records delivery attempts. Each consumer checks whether the event identifier has already been processed.

The deployment pipeline runs unit, contract, security, and integration tests. A canary release sends a small traffic percentage to the new order-service version. Dashboards show success ratio, p95 latency, queue age, payment failure rate, and dead-letter count. Alerts are routed to the operations technician with a short runbook.

Outcome

In a pilot, duplicate browser submissions produce one order because the idempotency key is reused. A simulated payment outage causes messages to queue rather than losing requests. After bounded retries, unresolved messages are visible in the dead-letter queue. Operators can trace a request from the API to payment and notification using the correlation identifier.

The solution does not provide instant global consistency, and notification delivery remains dependent on an external provider. These limitations are documented. The team plans a later improvement to add a self-service order-status page and automated restoration testing.

Learning Points

The case demonstrates that production orientation is broader than successful code execution. It requires explicit requirements, sensible boundaries, secure data handling, repeatable deployment, failure design, measurable operations, and honest documentation of trade-offs.

Challenges and Limitations

Serverless platforms can create vendor lock-in through proprietary events, identity models, databases, and deployment tools. Portable interfaces and contract tests reduce but do not eliminate this risk. Cold starts may affect latency, although their impact depends on runtime, memory allocation, traffic pattern, and provider implementation. Increasing memory may improve execution time while increasing unit cost; this must be measured rather than assumed.

Distributed systems introduce partial failure. A timeout does not reveal whether the remote operation failed before or after processing. Retrying a non-idempotent operation can therefore create duplicates. Idempotency keys, provider references, reconciliation jobs, and carefully chosen retry policies are safer than blind retries.

Eventual consistency can confuse users and support staff. The interface should expose meaningful states such as PENDING, AUTHORISED, and FAILED, together with a support correlation identifier. Operational complexity can also exceed the benefits of microservices. A modular monolith remains a legitimate professional option when independent scaling and deployment are not yet justified.

AI-assisted coding may accelerate scaffolding and test generation, but generated code can contain security defects, licence concerns, inaccurate APIs, or hidden assumptions. Teams remain accountable for review, testing, provenance, privacy, and compliance. Confidential source code and personal data should not be submitted to an AI tool without approval and suitable contractual safeguards.

Professional Project Deliverables and Best Practices

A complete diploma-level project should produce:

  • A requirements and assumptions document.
  • An architecture diagram and decision records.
  • API and event-contract documentation.
  • Source code with tests and code-review evidence.
  • IaC definitions and environment instructions.
  • A threat model and security-control explanation.
  • A deployment pipeline and rollback procedure.
  • Dashboards, alert definitions, and operational runbooks.
  • Test results, performance observations, cost assumptions, and limitations.
  • A final evaluation against the original requirements.

The strongest submissions distinguish facts from assumptions. They state which properties were tested, which were estimated, and which remain future work. They also explain why a simpler design was rejected or retained. Professional documentation is not an afterthought: it is part of the system’s maintainability and governance.

Chapter Summary

A professional cloud-native application project connects business requirements to architecture, implementation, security, delivery, operations, and evaluation. Serverless functions are useful for event-driven and variable workloads, while microservices can provide independent ownership and deployment. Both approaches introduce distributed-systems concerns, including retries, duplicate messages, partial failure, eventual consistency, and observability requirements.

A sound project defines service boundaries around business capabilities, uses synchronous APIs only where immediate responses are needed, and uses queues or events to decouple slow or failure-prone work. It applies least privilege, encryption, secret management, data minimisation, and auditability. Automated tests, Infrastructure as Code, immutable artifacts, progressive delivery, rollback planning, and operational runbooks turn an implementation into a production-oriented solution. Evaluation should use documented indicators such as success ratio, latency percentiles, queue age, cost, and recovery evidence. Finally, the architecture must be judged against team capability, operational complexity, legal duties, and business value rather than fashionable technology alone.

Key Terms

Cloud-native application: Software designed to use cloud capabilities such as elasticity, managed services, automation, and resilience.

Serverless function: A managed, event-triggered execution unit in which the provider operates the underlying servers.

Microservice: A comparatively small, independently deployable service aligned with a business capability.

API gateway: A managed entry point that routes, authenticates, throttles, and monitors API requests.

Event: A record that states that something happened, such as an order being submitted.

Queue: A buffer that stores messages until consumers process them.

Idempotency: The property that repeating an operation produces the same intended result rather than an unwanted duplicate.

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

Saga: A sequence of local transactions coordinated through messages and compensating actions.

Eventual consistency: A model in which distributed views may temporarily differ but converge when updates propagate.

Infrastructure as Code: Version-controlled, machine-readable definition and management of infrastructure.

Continuous integration: Automatically building and testing changes as they enter a shared repository.

Progressive delivery: Gradually exposing a new software version to users or traffic.

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

Service-level indicator: A measured value describing a service characteristic.

Service-level objective: A target value or range for a service-level indicator.

Least privilege: Granting an identity only the permissions required for its task.

Correlation identifier: A value propagated across components to connect related logs and traces.

Immutable artifact: A built software package that is versioned and not modified after creation.

Runbook: Operational instructions for diagnosing and responding to a known situation.

Review Questions

Short Answer Questions

  1. Distinguish a functional requirement from a non-functional requirement and give one example of each.
  2. Why are queues useful in a serverless and microservices architecture?
  3. Define idempotency and explain its importance for order submission.
  4. What is the difference between an SLI and an SLO?
  5. Name three types of telemetry used in observability.

Long Answer Questions

  1. Explain how a team should decide whether to use a serverless function, a microservice, or a modular monolith for a responsibility.
  2. Describe a secure deployment pipeline for the illustrative order-processing system.
  3. Explain how a saga can manage a business process that crosses order and payment services.
  4. Discuss the security and privacy controls required when an application processes orders and payment-related information.
  5. Evaluate the benefits and limitations of Infrastructure as Code in a small cloud-native project.

Analytical / Application Questions

  1. A queue consumer processes a payment message, times out after the provider may have completed the payment, and receives the message again. Design a safe processing strategy, including idempotency, reconciliation, and retry decisions.
  2. During one month, 9,950 of 10,000 valid API requests succeed. Calculate the success ratio and assess whether it meets a 99.5% SLO. State any assumptions about the measurement scope.
  3. A small team proposes twelve microservices for a simple college ordering system, each with its own database. Analyse the proposal and recommend a more appropriate initial architecture, including criteria for later decomposition.

Multiple Choice Questions with Answers

Question 1

Which component is primarily responsible for routing HTTPS requests and integrating authentication at the system boundary?

A. API gateway

B. Dead-letter queue

C. Notification service

D. Managed database

Correct Answer: A. API gateway

Question 2

What is the main purpose of an idempotency key in an order-submission API?

A. To encrypt the order payload

B. To prevent a repeated request from creating an unintended duplicate

C. To increase database storage capacity

D. To replace user authentication

Correct Answer: B. To prevent a repeated request from creating an unintended duplicate

Question 3

Which situation is most appropriate for asynchronous messaging?

A. Returning a validation error immediately

B. Checking whether a required field exists

C. Buffering payment work while an external provider is temporarily unavailable

D. Parsing a JSON request body

Correct Answer: C. Buffering payment work while an external provider is temporarily unavailable

Question 4

What should normally happen to a message that repeatedly fails processing after the configured retry limit?

A. It should be silently deleted

B. It should be placed in a dead-letter queue

C. It should be sent to every consumer again indefinitely

D. It should be written into source control

Correct Answer: B. It should be placed in a dead-letter queue

Question 5

Which principle requires a function to receive only the permissions necessary for its task?

A. Eventual consistency

B. Blue-green deployment

C. Least privilege

D. Schema versioning

Correct Answer: C. Least privilege

Question 6

If 9,950 of 10,000 valid requests succeed, what is the success ratio?

A. 0.950 or 95.0%

B. 0.985 or 98.5%

C. 0.995 or 99.5%

D. 1.005 or 100.5%

Correct Answer: C. 0.995 or 99.5%

Question 7

What does a p95 latency of 800 ms indicate?

A. Every request completes in exactly 800 ms

B. Approximately 95% of observations are at or below 800 ms

C. The average request takes 95 seconds

D. 5% of requests are guaranteed to fail

Correct Answer: B. Approximately 95% of observations are at or below 800 ms

Question 8

Which deployment approach gradually directs a small proportion of traffic to a new version before increasing exposure?

A. Canary deployment

B. Manual deletion

C. Schema rollback

D. Static analysis

Correct Answer: A. Canary deployment

Question 9

Why should raw payment-card details generally not be stored by the order application?

A. They make API responses too short

B. They eliminate the need for authentication

C. They increase compliance and security risk

D. They prevent all asynchronous processing

Correct Answer: C. They increase compliance and security risk

Question 10

Which statement best describes a service-level indicator?

A. A contractual remedy for an outage

B. A measured value describing a service characteristic

C. A source-code package format

D. A database migration technique

Correct Answer: B. A measured value describing a service characteristic

Foundations of Serverless Applications and Microservices
Chapter 15 of 15