Reading30 min read·Module 2

Microservices Architecture

Key concepts

  • Service decomposition

  • API-first design

  • Service discovery

  • Container orchestration

  • Independent deployability

Overview

Microservices architecture is an approach to building applications as a collection of small, independent services that communicate over well-defined APIs. Each service is developed, deployed, and scaled independently, owned by small teams, and focused on a specific business capability.

Understanding microservices architecture is essential for the SAA-C03 exam because it represents a fundamental shift from monolithic applications. You must know when to recommend microservices over monoliths, how to choose between container orchestration options (ECS vs EKS vs Fargate), implement service discovery and communication patterns, and design for resilience in distributed systems.

Microservices vs Monolith

Microservices break applications into independently deployable services. Each service has its own database, can use different technologies, and scales independently. This enables faster deployments but adds complexity in service discovery, distributed transactions, and monitoring.

Exam Tip

Exam questions often present scenarios involving monolithic applications with scaling or deployment challenges. The solution typically involves breaking the application into microservices using ECS, EKS, or Lambda with API Gateway and SQS/SNS for decoupling.


Key Concepts

Microservices Overview

Microservices Architecture Overview
Figure 1: Microservices architecture with independent services communicating via APIs

Microservices Principles

Microservices are built around these core principles:

  • Single Responsibility: Each service does one thing well
  • Independent Deployment: Deploy without affecting other services
  • Decentralized Data: Each service manages its own data store
  • API-First Design: Services communicate via well-defined APIs
  • Failure Isolation: One service failure doesn't cascade to others
  • Technology Agnostic: Teams can choose appropriate tech stack

Monolith vs Microservices

Monolith vs Microservices

AspectMonolithicMicroservices
DeploymentAll-or-nothingIndependent per service
ScalingScale entire applicationScale individual services
TechnologySingle stackPolyglot (different stacks)
DataShared databaseDatabase per service
Team StructureLarge, coordinated teamsSmall, autonomous teams
ComplexitySimpler initiallyDistributed system complexity
Failure ImpactCan bring down entire appIsolated to single service
TEXTWhen to Choose Each Approach
CHOOSE MONOLITH WHEN:
├── Small team (< 10 developers)
├── Simple domain with clear boundaries
├── Startup MVP or rapid prototyping
├── Limited operational expertise
└── Predictable, stable requirements

CHOOSE MICROSERVICES WHEN:
├── Large organization with multiple teams
├── Different services have different scaling needs
├── Need for technology flexibility
├── Frequent, independent deployments required
├── High availability requirements
└── Complex domain with clear bounded contexts

AWS Container Services

AWS Container Services Comparison
Figure 2: ECS, EKS, and Fargate container orchestration options

Amazon ECS (Elastic Container Service)

Amazon ECS

Amazon ECS is AWS's native container orchestration service that simplifies running Docker containers at scale. It integrates deeply with AWS services and offers two launch types:

  • EC2 Launch Type: You manage EC2 instances in your cluster
  • Fargate Launch Type: Serverless - AWS manages infrastructure
TEXTECS Architecture Components
ECS ARCHITECTURE:

CLUSTER
├── Logical grouping of tasks and services
└── Can span multiple Availability Zones

TASK DEFINITION
├── Blueprint for your application
├── Specifies container images
├── Defines CPU, memory, networking
├── IAM roles for containers
└── Similar to a Docker Compose file

SERVICE
├── Runs and maintains desired task count
├── Integrates with load balancers
├── Supports rolling deployments
├── Auto Scaling capabilities
└── Health check monitoring

TASK
├── Running instance of task definition
├── One or more containers
├── Ephemeral (can be replaced)
└── Runs on EC2 or Fargate

Amazon EKS (Elastic Kubernetes Service)

Amazon EKS

Amazon EKS runs Kubernetes on AWS without needing to install and operate your own Kubernetes control plane. Choose EKS when you need Kubernetes-specific features, cross-cloud portability, or have existing Kubernetes expertise.

TEXTEKS Architecture Components
EKS ARCHITECTURE:

CONTROL PLANE (AWS Managed)
├── Kubernetes API server
├── etcd (cluster state storage)
├── Controller manager
└── Scheduler

DATA PLANE (You manage or Fargate)
├── Worker Nodes (EC2 instances)
├── Node Groups (managed scaling)
└── Fargate Profiles (serverless)

KUBERNETES RESOURCES:
POD
├── Smallest deployable unit
├── Contains one or more containers
└── Shared networking and storage

DEPLOYMENT
├── Manages replica sets
├── Rolling updates
└── Rollback capabilities

SERVICE
├── Stable network endpoint
├── Load balancing across pods
└── Service discovery (DNS)

AWS Fargate

AWS Fargate

AWS Fargate is a serverless compute engine for containers that works with both ECS and EKS. You don't provision or manage servers - just specify CPU and memory requirements for your containers.

ECS vs EKS vs Fargate

FeatureECS (EC2)ECS (Fargate)EKS
ManagementManage EC2 instancesServerlessManage nodes or use Fargate
Learning CurveAWS-native, simplerVery simpleKubernetes expertise needed
PortabilityAWS onlyAWS onlyMulti-cloud with K8s
PricingEC2 + ECS (free)Per vCPU/memory/secondEKS fee + EC2 or Fargate
ScalingEC2 Auto ScalingAutomaticHPA + Cluster Autoscaler
Best ForAWS-native workloadsServerless containersKubernetes workloads

Service Discovery

Service Discovery Patterns
Figure 3: Service discovery approaches in AWS microservices

Service Discovery Options

Service Discovery

In a microservices architecture, services need to find each other dynamically. AWS provides several service discovery mechanisms:

  • AWS Cloud Map: Native service discovery for all AWS resources
  • ECS Service Discovery: Integrates with Route 53 Auto Naming
  • Kubernetes DNS: Built-in DNS for EKS services
  • Application Load Balancer: Layer 7 routing and discovery
TEXTService Discovery Patterns
CLIENT-SIDE DISCOVERY:
├── Service queries registry directly
├── Client chooses instance to call
├── Examples: Consul, Eureka
└── More complex client logic

SERVER-SIDE DISCOVERY (AWS Recommended):
├── Request goes to load balancer/DNS
├── Router queries registry and forwards
├── Examples: ALB, Route 53, Cloud Map
└── Simpler client, transparent discovery

AWS CLOUD MAP:
├── Define namespace (e.g., production.local)
├── Register service (e.g., orders.production.local)
├── Health checks update DNS records
├── Auto-removes unhealthy instances
└── API and DNS query support

ECS SERVICE DISCOVERY:
├── Automatic registration with Cloud Map
├── DNS A or SRV records
├── Integrates with Route 53
└── Health check integration

AWS Cloud Map Configuration

JSONCloud Map Service Registration
{
  "Namespace": {
    "Name": "production.local",
    "Type": "DNS_PRIVATE",
    "Vpc": "vpc-123456"
  },
  "Service": {
    "Name": "order-service",
    "DnsConfig": {
      "RoutingPolicy": "MULTIVALUE",
      "DnsRecords": [
        { "Type": "A", "TTL": 60 }
      ]
    },
    "HealthCheckCustomConfig": {
      "FailureThreshold": 3
    }
  }
}

Communication Patterns

Synchronous Communication

Synchronous (Request-Response)

Synchronous communication is when a service makes a request and waits for a response. This is common for real-time operations but creates tight coupling between services.

AWS Services: API Gateway, ALB, NLB

TEXTSynchronous Patterns
REST API (Most Common):
├── HTTP/HTTPS protocols
├── Stateless requests
├── JSON/XML payloads
└── Good for: CRUD operations, web APIs

gRPC:
├── High-performance RPC framework
├── Protocol Buffers for serialization
├── HTTP/2 with bidirectional streaming
└── Good for: Low-latency service-to-service

API GATEWAY PATTERN:
Internet → API Gateway → Microservices
├── Single entry point for clients
├── Request routing by path/header
├── Authentication & authorization
├── Rate limiting & throttling
├── Request/response transformation
└── Caching

Asynchronous Communication

Asynchronous (Event-Driven)

Asynchronous communication decouples services by using message queues or event streams. Services don't wait for responses, improving resilience and scalability.

AWS Services: SQS, SNS, EventBridge, Kinesis

TEXTAsynchronous Patterns
MESSAGE QUEUES (SQS):
├── Point-to-point communication
├── Guaranteed delivery
├── Message persistence
├── Dead-letter queues for failures
└── Good for: Work distribution, decoupling

PUBLISH/SUBSCRIBE (SNS):
├── One-to-many messaging
├── Multiple subscriber types
├── Fan-out pattern
└── Good for: Notifications, broadcasting

EVENT STREAMING (Kinesis/EventBridge):
├── Real-time data streams
├── Event sourcing patterns
├── Multiple consumers
└── Good for: Analytics, real-time processing

Communication Pattern Selection

PatternCouplingUse CaseAWS Service
Sync REST APITightCRUD, real-time queriesAPI Gateway + ALB
Async QueueLooseBackground processingSQS
Pub/SubLooseEvent notificationsSNS + SQS
Event StreamLooseReal-time analyticsKinesis, EventBridge

API Gateway Pattern

API Gateway Pattern
Figure 4: API Gateway as single entry point routing to microservices

API Gateway Pattern

The API Gateway pattern provides a single entry point for all client requests, routing them to appropriate microservices. It handles cross-cutting concerns like authentication, rate limiting, and monitoring.

TEXTAPI Gateway Architecture
API GATEWAY PATTERN:

                    ┌──────────────────┐
                    │   API Gateway    │
                    │   ─────────────  │
Mobile ───────────→ │ • Authentication │
Web App ──────────→ │ • Rate Limiting  │ ──→ Microservices
Partners ─────────→ │ • Routing        │
                    │ • Transformation │
                    │ • Caching        │
                    └──────────────────┘

AMAZON API GATEWAY FEATURES:
├── REST APIs (full-featured)
│   ├── Request/response transformation
│   ├── SDK generation
│   └── API caching
│
├── HTTP APIs (simpler, faster, cheaper)
│   ├── Lower latency
│   ├── Native OpenID Connect/OAuth 2.0
│   └── 71% cheaper than REST APIs
│
└── WebSocket APIs
    ├── Real-time bidirectional
    ├── Chat, gaming, trading
    └── Connection state management

API Gateway Integration Types

API Gateway Integration Types

IntegrationDescriptionUse Case
Lambda ProxyPasses entire request to LambdaServerless backends
HTTP ProxyForwards to HTTP endpointsECS/EKS services, external APIs
VPC LinkPrivate integration to VPC resourcesInternal microservices
MockReturns hardcoded responseTesting, stubs

Distributed Transaction Patterns

Saga Pattern

Saga Pattern

The Saga pattern manages distributed transactions across microservices. Instead of a single ACID transaction, it uses a sequence of local transactions with compensating actions for rollbacks.

TEXTSaga Pattern with Step Functions
SAGA PATTERN (Order Processing Example):

SUCCESS PATH:
1. Create Order      → Order Service
2. Reserve Inventory → Inventory Service
3. Process Payment   → Payment Service
4. Ship Order        → Shipping Service
✓ Complete

COMPENSATING TRANSACTIONS (on failure):
If Payment fails:
├── 3. Payment Failed     → Trigger compensation
├── 2. Release Inventory  → Inventory Service
├── 1. Cancel Order       → Order Service
└── Return error to user

AWS STEP FUNCTIONS FOR SAGA:
├── Visual workflow designer
├── Error handling & retries
├── Timeout management
├── Parallel execution
├── State machine definition
└── Integration with Lambda, ECS, SQS

Best Practices

Design Principles

  1. Design for Failure: Implement circuit breakers, retries, and timeouts
  2. Decentralize Data: Each service owns its data store
  3. API Versioning: Version APIs to enable independent deployments
  4. Stateless Services: Store state externally (DynamoDB, ElastiCache)
  5. Automate Everything: CI/CD pipelines for each microservice
  6. Monitor Extensively: Distributed tracing, centralized logging
  7. Start Simple: Begin with a monolith if uncertain, extract later

Container Best Practices

TEXTContainer Best Practices
IMAGE OPTIMIZATION:
├── Use minimal base images (Alpine, distroless)
├── Multi-stage builds to reduce size
├── Scan images for vulnerabilities (ECR scanning)
└── Tag images with git SHA, not just 'latest'

RESOURCE MANAGEMENT:
├── Set CPU and memory limits
├── Use appropriate instance types (Fargate vCPU/memory)
├── Implement health checks
└── Configure graceful shutdown

SECURITY:
├── Run as non-root user
├── Use IAM roles for tasks (not embedded credentials)
├── Enable secrets management (Secrets Manager)
├── Network isolation with security groups
└── Enable encryption in transit

DEPLOYMENT:
├── Blue/green or canary deployments
├── Rolling updates with health checks
├── Automated rollback on failures
└── Immutable infrastructure

Common Exam Scenarios

Exam Scenarios

ScenarioSolutionWhy
Monolith with scaling issuesRefactor to microservices on ECS/EKSIndependent scaling per service
Team needs Kubernetes portabilityAmazon EKSStandard Kubernetes APIs
Serverless containers, no infraAWS FargateNo servers to manage
Services need to discover each otherAWS Cloud Map + Route 53Dynamic service discovery
Decouple order processingSQS between servicesAsync, fault-tolerant
Single API entry pointAPI GatewayRouting, auth, rate limiting
Distributed transaction across servicesStep Functions (Saga)Orchestration with compensation
Container images with secretsSecrets Manager + IAM rolesNo embedded credentials

Common Pitfalls

Pitfall 1: Distributed Monolith

Mistake: Creating microservices that are tightly coupled through synchronous calls.

Why it fails: Defeats the purpose of microservices; one service failure cascades.

Correct Approach: Use async communication (SQS, SNS) for loose coupling; design for failure.

Pitfall 2: Shared Database

Mistake: Multiple microservices accessing the same database.

Why it fails: Creates tight coupling; schema changes affect multiple services.

Correct Approach: Each service owns its database; use APIs or events to share data.

Pitfall 3: Wrong Container Orchestrator

Mistake: Choosing EKS when team has no Kubernetes experience.

Why it fails: Steep learning curve; operational overhead; potential misconfigurations.

Correct Approach: Start with ECS/Fargate for simpler operations; migrate to EKS if needed.

Pitfall 4: No Service Discovery

Mistake: Hardcoding service endpoints or IP addresses.

Why it fails: Services can't scale or failover; manual updates required.

Correct Approach: Use Cloud Map, ALB, or Kubernetes DNS for dynamic discovery.

Pitfall 5: Missing Observability

Mistake: Deploying microservices without centralized logging and tracing.

Why it fails: Debugging distributed systems becomes impossible.

Correct Approach: Use X-Ray for tracing, CloudWatch for logs, Container Insights for metrics.



Quick Reference

Container Service Decision Matrix

Container Service Selection

RequirementRecommended Service
Simplest container deploymentECS + Fargate
Kubernetes requiredEKS (+ Fargate optional)
Need to manage EC2 instancesECS or EKS with EC2
Maximum portabilityEKS
Lowest operational overheadFargate
Cost-sensitive, steady workloadECS EC2 + Reserved/Spot

Communication Pattern Quick Reference

TEXTCommunication Pattern Decision
CHOOSE SYNCHRONOUS (API Gateway, ALB):
├── Real-time response required
├── Simple request-response
├── User-facing operations
└── Query operations

CHOOSE ASYNCHRONOUS (SQS, SNS, EventBridge):
├── Can tolerate latency
├── Need fault tolerance
├── Background processing
├── Event broadcasting
├── Workload decoupling
└── Fan-out scenarios

ECS Task Definition Example

JSONECS Task Definition
{
  "family": "order-service",
  "networkMode": "awsvpc",
  "requiresCompatibilities": ["FARGATE"],
  "cpu": "256",
  "memory": "512",
  "executionRoleArn": "arn:aws:iam::123456789012:role/ecsTaskExecutionRole",
  "taskRoleArn": "arn:aws:iam::123456789012:role/orderServiceRole",
  "containerDefinitions": [
    {
      "name": "order-api",
      "image": "123456789012.dkr.ecr.us-east-1.amazonaws.com/order-service:v1.2.3",
      "portMappings": [
        { "containerPort": 8080, "protocol": "tcp" }
      ],
      "logConfiguration": {
        "logDriver": "awslogs",
        "options": {
          "awslogs-group": "/ecs/order-service",
          "awslogs-region": "us-east-1",
          "awslogs-stream-prefix": "ecs"
        }
      },
      "healthCheck": {
        "command": ["CMD-SHELL", "curl -f http://localhost:8080/health || exit 1"],
        "interval": 30,
        "timeout": 5,
        "retries": 3
      },
      "secrets": [
        {
          "name": "DB_PASSWORD",
          "valueFrom": "arn:aws:secretsmanager:us-east-1:123456789012:secret:db-password"
        }
      ]
    }
  ]
}

Test Your Knowledge

Q

A company is migrating a monolithic application to microservices. Different services have different scaling requirements - one handles thousands of requests per second while another processes batch jobs hourly. Which is the primary benefit of microservices for this scenario?

AReduced development costs
BIndependent scaling of services
CSimpler deployment process
DShared database access
Q

A solutions architect needs to choose between ECS and EKS for a new container workload. The team has no Kubernetes experience but needs to deploy quickly with minimal operational overhead. What is the recommended approach?

AEKS with Fargate for serverless Kubernetes
BECS with Fargate for simplest deployment
CECS with EC2 for maximum control
DEKS with managed node groups
Q

How should microservices discover each other's endpoints in an AWS environment?

AHardcode IP addresses in configuration
BUse AWS Cloud Map for service discovery
CStore endpoints in S3 bucket
DUse CloudWatch for service registry
Q

A distributed e-commerce application needs to process orders across multiple microservices (inventory, payment, shipping). If the payment service fails, previous operations must be rolled back. Which pattern should be used?

ATwo-phase commit across all databases
BSaga pattern with Step Functions
CSingle shared database for all services
DRetry the failed operation indefinitely

Further Reading

Related services

ECSEKSApp MeshCloud Map