1
API Design Principles are guidelines that help you build APIs that are scalable,
maintainable, secure, and easy to use. Since you’re preparing for system design and
AWS-style discussions, I’ll explain this in an interview-ready structured format.
Consistency
Consistency makes APIs predictable.
✔ Use consistent naming conventions
• Use nouns, not verbs
/getUsers
/users
• Use plural resource names
/orders
/customers/123/orders
✔ Standard HTTP methods
• GET → Fetch data
• POST → Create
• PUT → Full update
• PATCH → Partial update
• DELETE → Remove
Consistency reduces developer confusion.
Resource-Oriented Design (RESTful Thinking)
Design APIs around resources, not actions.
Example:
/orders
/orders/{orderId}
/orders/{orderId}/items
Think in terms of:
• Entities (User, Order, Product)
• Relationships
• Hierarchies
Proper HTTP Status Codes
2
Return meaningful responses.
Scenario Status Code
Success 200 OK
Created 201 Created
No Content 204
Bad Request 400
Unauthorized 401
Forbidden 403
Not Found 404
Server Error 500
Interview Tip: Don’t always return 200. It’s a common mistake.
Versioning
APIs evolve. Never break clients.
Common strategies:
• URI versioning → /v1/orders
• Header versioning
• Query param versioning
Best practice for interviews:
/api/v1/orders
Statelessness
Each request should contain everything needed.
✔ No server-side session storage
✔ Use JWT or tokens
✔ Supports horizontal scaling
This is critical in microservices architecture.
Pagination, Filtering, Sorting
Avoid returning huge datasets.
Pagination
3
GET /orders?page=1&limit=20
Filtering
GET /orders?status=shipped
Sorting
GET /orders?sort=createdAt_desc
Makes API scalable.
Idempotency
Important for distributed systems.
• GET, PUT, DELETE → Idempotent
• POST → Not naturally idempotent
To make POST safe:
• Use Idempotency-Key header
• Prevent duplicate payments/orders
Very important for payment APIs.
Security First
✔ HTTPS always
✔ Authentication (JWT, OAuth2)
✔ Authorization (RBAC/ABAC)
✔ Rate Limiting
✔ Input Validation
✔ Encryption for sensitive data
In AWS:
• API Gateway + IAM
• Cognito
• WAF
Clear Error Handling
Provide structured error responses.
Example:
4
{
"errorCode": "ORDER_NOT_FOUND",
"message": "The order with ID 123 does not exist",
"timestamp": "2026-02-12T10:00:00Z"
}
Never expose:
• Stack traces
• Internal DB errors
Documentation
An API without documentation is useless.
Use:
• OpenAPI (Swagger)
• API contracts
• Example requests/responses
Good docs = developer adoption.
Backward Compatibility
Never remove fields suddenly.
Instead:
• Deprecate
• Announce migration window
• Maintain old version
Performance & Efficiency
✔ Compression (gzip)
✔ Caching (ETag, Cache-Control)
✔ Minimize payload
✔ Async processing when needed
Example:
• Use 202 Accepted for async jobs.
5
Observability
Production-ready APIs need:
• Logging
• Metrics
• Tracing
• Correlation IDs
Especially important in microservices.
Interview Summary (30-Second Answer)
If asked:
“What are key API design principles?”
You can say:
A well-designed API should be resource-oriented, consistent, stateless, properly versioned,
secure, idempotent where required, and should use correct HTTP status codes. It must
support pagination, filtering, and provide structured error responses. Additionally, it should be
backward-compatible, observable, and well documented for maintainability and scalability.
2222222222************************
Here’s a clear, interview-ready REST vs GraphQL design comparison — structured for
system design discussions.
Core Philosophy
REST GraphQL
Resource-based architecture Query-based architecture
Multiple endpoints Single endpoint
Fixed data structure Client defines response shape
REST: Server decides the data structure.
GraphQL: Client decides the data structure.
Endpoint Design
REST
GET /users
GET /users/123
GET /users/123/orders
6
Each resource has its own endpoint.
GraphQL
POST /graphql
Single endpoint. Client sends query:
query {
user(id: "123") {
name
orders {
id
amount
}
}
}
Overfetching vs Underfetching
REST Problem
If you call:
GET /users/123
You may get:
• id
• name
• email
• address
• createdAt
• metadata
But maybe you only needed name.
Or you may need:
• user data
• user orders
Which requires:
GET /users/123
GET /users/123/orders
7
→ Multiple calls (underfetching).
GraphQL Advantage
You ask exactly what you need:
query {
user(id: "123") {
name
orders {
id
}
}
}
✔ No overfetching
✔ No multiple network calls
Performance Considerations
Aspect REST GraphQL
Caching Easy (HTTP caching, CDN) Harder (POST-based queries)
Network calls Multiple calls possible Single call
Payload size Fixed response Flexible & optimized
Server complexity Simple More complex
Key Insight:
REST is easier to cache at CDN level.
GraphQL requires custom caching strategies.
Versioning
REST
Common:
/api/v1/users
/api/v2/users
Version in URL.
8
GraphQL
Typically:
• No versioning
• Add new fields
• Deprecate old fields
GraphQL evolves without breaking clients.
Error Handling
REST
Uses HTTP status codes:
• 200
• 400
• 404
• 500
GraphQL
Usually returns:
200 OK
With:
{
"data": {},
"errors": []
}
Errors handled in response body.
Learning Curve
REST GraphQL
Easy to start Steeper learning curve
Simple mental model Requires schema design
Widely adopted Growing adoption
9
When to Use REST
✔ Simple CRUD applications
✔ Public APIs
✔ Microservices communication
✔ Systems needing strong HTTP caching
✔ Server-to-server communication
Example:
• Payment processing API
• Order management backend
• Internal AWS microservices
When to Use GraphQL
✔ Mobile applications (avoid multiple calls)
✔ Complex UI with dynamic data needs
✔ Frontend-heavy applications
✔ When frontend teams need flexibility
Example:
• Social media app
• E-commerce frontend with dynamic UI
• Dashboard apps
System Design Perspective
REST works best when:
• System is microservice-based
• Resources are well defined
• Simpler infrastructure
• Need API Gateway + CDN caching
GraphQL works best when:
• Many related resources
• Client-specific data views
• Need aggregation layer (BFF pattern)
• Reducing round trips is critical
Often used as:
Client → GraphQL Layer → Microservices (REST)
10
GraphQL acts as an aggregation layer.
Trade-Off Summary
Dimension REST GraphQL
Simplicity High Medium
Flexibility Medium High
Caching Native HTTP Custom
Tooling Mature Mature but complex
Backend load Predictable Can be heavy
Schema contract Informal Strongly typed
Interview-Ready 45-Second Answer
If interviewer asks:
“When would you choose REST over GraphQL?”
You can say:
REST is ideal when you have well-defined resources, need strong HTTP semantics and
caching, and want simplicity in backend implementation. GraphQL is better when frontend
applications require flexible data fetching, need to avoid overfetching or multiple round trips,
and when building aggregation layers over multiple microservices. In large-scale systems,
GraphQL often acts as a BFF layer on top of REST microservices.
3333333333333333333333333333333333333333333333333333333
interview-ready REST vs GraphQL design comparison — structured for system design
discussions.
Core Philosophy
REST GraphQL
Resource-based architecture Query-based architecture
Multiple endpoints Single endpoint
Fixed data structure Client defines response shape
REST: Server decides the data structure.
GraphQL: Client decides the data structure.
11
Endpoint Design
REST
GET /users
GET /users/123
GET /users/123/orders
Each resource has its own endpoint.
GraphQL
POST /graphql
Single endpoint. Client sends query:
query {
user(id: "123") {
name
orders {
id
amount
}
}
}
Overfetching vs Underfetching
REST Problem
If you call:
GET /users/123
You may get:
• id
• name
• email
• address
• createdAt
• metadata
But maybe you only needed name.
Or you may need:
12
• user data
• user orders
Which requires:
GET /users/123
GET /users/123/orders
→ Multiple calls (underfetching).
GraphQL Advantage
You ask exactly what you need:
query {
user(id: "123") {
name
orders {
id
}
}
}
✔ No overfetching
✔ No multiple network calls
Performance Considerations
Aspect REST GraphQL
Caching Easy (HTTP caching, CDN) Harder (POST-based queries)
Network calls Multiple calls possible Single call
Payload size Fixed response Flexible & optimized
Server complexity Simple More complex
Key Insight:
REST is easier to cache at CDN level.
GraphQL requires custom caching strategies.
Versioning
REST
13
Common:
/api/v1/users
/api/v2/users
Version in URL.
GraphQL
Typically:
• No versioning
• Add new fields
• Deprecate old fields
GraphQL evolves without breaking clients.
Error Handling
REST
Uses HTTP status codes:
• 200
• 400
• 404
• 500
GraphQL
Usually returns:
200 OK
With:
{
"data": {},
"errors": []
}
Errors handled in response body.
Learning Curve
14
REST GraphQL
Easy to start Steeper learning curve
Simple mental model Requires schema design
Widely adopted Growing adoption
When to Use REST
✔ Simple CRUD applications
✔ Public APIs
✔ Microservices communication
✔ Systems needing strong HTTP caching
✔ Server-to-server communication
Example:
• Payment processing API
• Order management backend
• Internal AWS microservices
When to Use GraphQL
✔ Mobile applications (avoid multiple calls)
✔ Complex UI with dynamic data needs
✔ Frontend-heavy applications
✔ When frontend teams need flexibility
Example:
• Social media app
• E-commerce frontend with dynamic UI
• Dashboard apps
System Design Perspective
REST works best when:
• System is microservice-based
• Resources are well defined
• Simpler infrastructure
• Need API Gateway + CDN caching
GraphQL works best when:
15
• Many related resources
• Client-specific data views
• Need aggregation layer (BFF pattern)
• Reducing round trips is critical
Often used as:
Client → GraphQL Layer → Microservices (REST)
GraphQL acts as an aggregation layer.
Trade-Off Summary
Dimension REST GraphQL
Simplicity High Medium
Flexibility Medium High
Caching Native HTTP Custom
Tooling Mature Mature but complex
Backend load Predictable Can be heavy
Schema contract Informal Strongly typed
Interview-Ready 45-Second Answer
If interviewer asks:
“When would you choose REST over GraphQL?”
You can say:
REST is ideal when you have well-defined resources, need strong HTTP semantics and
caching, and want simplicity in backend implementation. GraphQL is better when frontend
applications require flexible data fetching, need to avoid overfetching or multiple round trips,
and when building aggregation layers over multiple microservices. In large-scale systems,
GraphQL often acts as a BFF layer on top of REST microservices.
If you'd like next, I can give:
• REST vs GraphQL in microservices architecture
• Performance pitfalls in GraphQL
• Designing a GraphQL API for an e-commerce system
• AWS implementation comparison
16
Tell me which direction you want to go.
REST vs GraphQL in microservices architecture
REST vs GraphQL in microservices architecture
Here’s a system-design level explanation of REST vs GraphQL in a microservices
architecture, structured the way you’d answer in an interview.
Where They Sit in Architecture
REST in Microservices (Most Common Pattern)
Client → API Gateway → Microservice A
→ Microservice B
→ Microservice C
Each microservice:
• Owns its database
• Exposes REST APIs
• Communicates via REST or messaging
Example:
• User Service → /users
• Order Service → /orders
• Payment Service → /payments
This is the classic distributed service model.
GraphQL in Microservices (Aggregation Layer Pattern)
Client → GraphQL Gateway (BFF Layer)
↓
User Service (REST)
Order Service (REST)
Payment Service (REST)
GraphQL acts as:
• A single entry point
• An orchestrator/aggregator
• A Backend-for-Frontend (BFF)
Microservices often still use REST internally.
17
Key Architectural Differences
Aspect REST Microservices GraphQL Microservices
API Exposure Each service exposed One unified endpoint
Client Calls Multiple calls possible Single query
Aggregation Client handles Server handles
Coupling Loosely coupled Slight coupling at GraphQL layer
Caching Easy via HTTP/CDN More complex
Complexity Lower Higher
Data Fetching Scenario (Important for Interviews)
Scenario:
Frontend needs:
• User profile
• User orders
• Payment status
REST Approach
Client makes multiple requests:
GET /users/123
GET /orders?userId=123
GET /payments?userId=123
Problems:
• Multiple round trips
• Client-side stitching
• Overfetching possible
GraphQL Approach
Single query:
query {
user(id: "123") {
18
name
orders {
id
amount
}
payments {
status
}
}
}
GraphQL gateway:
• Calls User service
• Calls Order service
• Calls Payment service
• Merges response
✔ Single client call
✔ Reduced round trips
Service-to-Service Communication
Important distinction:
Even when using GraphQL externally,
Internally, services usually talk via:
• REST
• gRPC
• Async messaging (Kafka/SQS)
GraphQL is typically not used for service-to-service communication.
Scaling Considerations
REST Microservices Scaling
Each service:
• Independently scalable
• Clear ownership
19
• Predictable load
Very cloud-native friendly.
GraphQL Gateway Scaling
GraphQL layer:
• Becomes aggregation bottleneck
• Needs:
o Caching
o Batching (DataLoader pattern)
o Query depth limiting
o Rate limiting
If poorly designed:
• N+1 query problem
• Expensive nested queries
• Heavy DB load
Caching Differences
REST
• HTTP caching
• CDN friendly
• ETags
• Cache-Control headers
Very straightforward.
GraphQL
• Queries are POST-based
• Harder to cache at CDN
• Need:
o Persisted queries
o Custom caching layer
o Response-level caching
20
Organizational Perspective
REST Works Best When:
• Many independent teams
• Services independently deployed
• Backend complexity must remain simple
• Public APIs exposed
Common in:
• Banking systems
• Payment systems
• Enterprise backends
GraphQL Works Best When:
• Frontend-heavy product
• Multiple clients (Web + Mobile)
• Rapid UI iteration
• Need flexible data views
Common in:
• E-commerce
• Social media apps
• SaaS dashboards
Hybrid Pattern (Most Realistic Architecture)
Most companies use:
Client → GraphQL (BFF Layer)
↓
REST Microservices
↓
Databases
This gives:
• Frontend flexibility
• Backend service isolation
• Team independence
21
• Clean domain separation
Drawbacks Comparison
REST Drawbacks
• Overfetching
• Multiple network calls
• Client-side aggregation complexity
GraphQL Drawbacks
• Gateway complexity
• Harder observability
• Harder caching
• Query performance risk
• Increased coupling at aggregation layer
Interview-Ready 60-Second Answer
If interviewer asks:
“How does REST compare to GraphQL in microservices?”
You can say:
In microservices architecture, REST is typically used for service-to-service communication
because it keeps services loosely coupled, independently scalable, and easy to cache using
HTTP semantics. GraphQL is often introduced as a gateway or BFF layer to aggregate data
from multiple REST microservices and provide a flexible interface to frontend clients. REST
simplifies backend ownership and scaling, while GraphQL simplifies client data fetching and
reduces round trips. In large-scale systems, a hybrid model is commonly used, where
GraphQL handles client aggregation and REST powers internal service communication.
44444444444444444444444444444
API Design for Microservices – Interview Answer
If the interviewer asks:
“How do you design APIs for a microservices architecture?”
You can structure your answer like this:
Service Ownership & Domain-Driven Design
First, I design APIs around business domains, not technical layers.
22
• Each microservice owns:
o Its data
o Its business logic
o Its API contract
Example:
• User Service → /users
• Order Service → /orders
• Payment Service → /payments
This ensures:
• Loose coupling
• Independent deployments
• Clear service boundaries
Resource-Oriented REST Design
For microservices, I prefer RESTful APIs internally.
Principles:
• Use nouns, not verbs
/orders
/createOrder
• Standard HTTP methods (GET, POST, PUT, DELETE)
• Proper status codes
Example:
GET /orders/{id}
POST /orders
PATCH /orders/{id}
Consistency is critical when multiple teams build services.
Stateless APIs
Each request must be self-contained.
• No server-side sessions
• Use JWT or OAuth tokens
• Makes horizontal scaling easy
23
This is important in Kubernetes or AWS auto-scaling environments.
API Gateway Pattern
Clients should not directly call individual microservices.
Instead:
Client → API Gateway → Microservices
Gateway handles:
• Authentication
• Rate limiting
• Routing
• Logging
• Throttling
• SSL termination
This keeps services clean and focused.
Inter-Service Communication
For synchronous calls:
• REST or gRPC
For asynchronous communication:
• Kafka / SQS / SNS / event-driven approach
Rule of thumb:
• Use async messaging for decoupling
• Avoid long dependency chains
Versioning & Backward Compatibility
Microservices evolve independently.
Strategies:
• /api/v1/orders
• Additive changes only
• Deprecation policy
Never break existing consumers.
24
Idempotency & Reliability
Important in distributed systems.
• Make PUT & DELETE idempotent
• Use Idempotency-Key for POST (e.g., payments)
• Handle retries safely
Prevents duplicate transactions.
Pagination, Filtering, Sorting
Avoid large payloads:
GET /orders?page=1&limit=20
GET /orders?status=shipped
Prevents performance bottlenecks.
Security Best Practices
• HTTPS everywhere
• Token-based authentication (JWT / OAuth)
• RBAC authorization
• Input validation
• Rate limiting
• API throttling
In AWS:
• API Gateway + Cognito + IAM + WAF
Observability & Monitoring
Microservices require visibility.
Include:
• Correlation IDs
• Structured logging
• Metrics
• Distributed tracing (e.g., X-Ray)
Helps debug cross-service flows.
25
Architecture Summary
A clean microservices API design looks like:
Client
↓
API Gateway
↓
Microservices (REST)
↓
Databases (per service)
Optional:
• Event bus for async communication.
60-Second Interview Summary (High-Impact Answer)
You can conclude with:
When designing APIs for microservices, I focus on domain-driven boundaries so each
service owns its data and API contract. I design resource-oriented, stateless REST APIs with
proper versioning, idempotency, and structured error handling. An API Gateway handles
cross-cutting concerns like authentication and rate limiting. For communication, I prefer
synchronous REST or gRPC where needed and asynchronous messaging for loose
coupling. Finally, I ensure backward compatibility, observability, and scalability as first-class
design principles.
5555555555555555555555555555555555555555555555555555555555555555
🏗 Advanced API Design for Microservices (Senior-Level Answer)
Start With Domain Boundaries (DDD + Bounded Context)
At senior level, you don’t start with endpoints.
You start with:
• Clear bounded contexts
• Data ownership
• Isolation strategy
• Team autonomy
Example domains:
• Identity
• Catalog
• Pricing
26
• Cart
• Order
• Payment
• Inventory
• Fulfillment
• Notifications
Each service:
• Owns its database
• Owns its API contract
• Has independent CI/CD pipeline
Goal:
High cohesion within service, low coupling between services.
API Exposure Strategy
External vs Internal APIs
I separate:
External API Layer (North-South)
• API Gateway
• GraphQL BFF (optional)
• Rate limiting
• Auth
• WAF
• Monetization
• Request validation
Internal Service APIs (East-West)
• REST or gRPC
• Service mesh (mTLS)
• Strict SLAs
• Circuit breakers
API Contract Design Principles
At senior level, you must talk about contracts.
27
API as a Product
• Backward compatibility guaranteed
• Semantic versioning
• Contract-first development (OpenAPI / Protobuf)
• Consumer-driven contracts (CDC testing)
I avoid breaking changes:
• Only additive changes
• Deprecation strategy with sunset headers
Idempotency & Distributed Reliability
Critical in payments and orders.
Example: Order Creation
Instead of:
POST /orders
We enforce:
• Idempotency-Key header
• Retry-safe design
• At-least-once delivery tolerance
Why?
Because in distributed systems:
• Network failures
• Client retries
• Duplicate submissions
• Partial timeouts
Without idempotency → duplicate payments.
Event-Driven API Strategy
Senior-level systems avoid deep synchronous chains.
Bad:
Order → Payment → Inventory → Shipping (sync chain)
✔ Better:
• OrderCreated event
28
• PaymentProcessed event
• InventoryReserved event
• Saga orchestration
Patterns used:
• Saga (orchestration or choreography)
• Outbox pattern
• Event sourcing (optional)
APIs should reflect eventual consistency realities.
Data Ownership & Avoiding Distributed Joins
Common mistake:
Service A calls B calls C to assemble response.
Senior solution:
• API composition layer (BFF)
• Precomputed read models
• CQRS pattern
• Caching layer
Never allow:
Cross-database joins across services.
Scalability Design
Design APIs assuming:
• Millions of users
• Flash sales
• Traffic spikes
Techniques:
Rate Limiting
Protect payment & order APIs.
Bulkheads
Isolate failures (cart failure should not break product browsing).
Circuit Breakers
Prevent cascading failures.
29
Read/Write Separation
Catalog reads cached aggressively.
Pagination + Cursor-based pagination
For large datasets.
Security & Compliance (Senior Depth)
For payment systems:
• PCI compliance
• Encryption at rest & in transit
• Field-level encryption
• Tokenization of card data
• mTLS internally
• Fine-grained authorization (RBAC/ABAC)
• Audit trails
Also:
• Do not expose internal IDs
• Use opaque identifiers (UUID)
Observability & Operational Maturity
At scale, debugging is harder than coding.
Every API must include:
• Correlation ID
• Structured logs
• Metrics (p95, p99 latency)
• Distributed tracing
• Error budget tracking
• SLIs/SLOs
APIs must be observable first-class citizens.
Multi-Region & High Availability
Senior-level thinking includes:
• Active-active setup
30
• Region-based routing
• Idempotency across regions
• Data replication strategy
• Eventual consistency handling
Payment APIs especially must handle region failover without double charging.
Performance & Cost Awareness
I design APIs minimizing:
• Chattiness
• Payload size
• Deep nesting
• N+1 issues
Introduce:
• Response shaping
• Compression
• Async processing (202 Accepted for long tasks)
• CDN caching for public APIs
Evolution Strategy
Large systems survive years.
I plan for:
• Contract testing in CI
• Schema registry for events
• Backward-compatible changes only
• Deprecation workflows
• API lifecycle governance
Failure Modeling (This Impresses Interviewers)
I ask:
What happens if:
• Payment succeeds but inventory fails?
• Order service crashes mid-transaction?
31
• Kafka message is delivered twice?
• Service times out but still processes request?
Senior-level answer:
Design for partial failure, retries, and eventual consistency.
2-Minute Senior-Level Interview Answer
If asked:
“How would you design APIs for a large-scale e-commerce payment system?”
You can say:
At a senior level, I design APIs around domain-driven boundaries ensuring each
microservice owns its data and contract. External APIs are exposed through a gateway or
BFF layer, while internal communication uses REST or gRPC secured via mTLS. I enforce
contract-first development, backward compatibility, and consumer-driven contract testing.
For critical workflows like order and payment processing, I ensure idempotency and
implement Saga patterns to handle distributed consistency. I avoid synchronous call chains
by using event-driven communication and the Outbox pattern. Security, observability, rate
limiting, and circuit breakers are built in from day one. Finally, I design for multi-region
resilience, failure tolerance, and operational maturity, ensuring the system remains scalable,
evolvable, and compliant over time.
666666666666666666666666666666666666666666666666666
AWS-Focused Microservices API Design (Senior-Level)
When designing APIs for microservices on AWS, I focus on:
1. Scalability
2. Resilience
3. Security
4. Loose coupling
5. Observability
6. Cost optimization
7. Evolution over time
Let’s walk through it layer by layer.
High-Level Architecture on AWS
Typical AWS microservices API architecture:
Client (Web/Mobile)
|
32
Amazon CloudFront
|
Amazon API Gateway
|
VPC (Private Subnets)
|
┌───────────────┬───────────────┬───────────────┐
| Order Service | Payment Svc | Inventory Svc |
| (ECS/Lambda) | (ECS/Lambda) | (ECS/Lambda) |
└───────────────┴───────────────┴───────────────┘
|
RDS / DynamoDB
|
EventBridge / SNS / SQS
API Gateway Design Strategy
Why API Gateway?
It provides:
• Centralized entry point
• Authentication & authorization
• Rate limiting
• Request validation
• Throttling
• Caching
• WAF integration
Production Setup:
• Edge-optimized API Gateway for global APIs
• Private API Gateway for internal services
• Integrated with:
o Lambda
o ECS via ALB
o Step Functions
33
Best Practice:
• Keep it lightweight — no business logic inside API Gateway.
• Use it for policy enforcement only.
Authentication & Authorization (AWS Native)
For public APIs:
• Amazon Cognito (OIDC + OAuth2)
• JWT-based authorization
For service-to-service:
• IAM roles
• mTLS via App Mesh (optional)
• AWS STS temporary credentials
Fine-Grained Access:
• API Gateway authorizers
• IAM policies
• Resource-level permissions
Senior insight:
Always enforce Zero Trust — never assume internal network is trusted.
Compute Layer Choices
Option AWS Lambda (Serverless)
Best for:
• Event-driven APIs
• Variable traffic
• Rapid scaling
Pros:
• Auto-scaling
• No server management
• Cost-efficient for burst traffic
Cons:
• Cold starts
• Long-running tasks limitations
34
Option ECS Fargate
Best for:
• Long-running services
• Heavy workloads
• Predictable performance
Pros:
• Full container control
• No EC2 management
• Better for complex microservices
Option EKS
Best for:
• Large-scale Kubernetes-based ecosystems
API Data Layer Design
DynamoDB (Preferred for Microservices)
• Single-table design per service
• Partition key per access pattern
• Avoid cross-service joins
• Enable auto-scaling
RDS
• Use when:
o Strong relational integrity required
• Prefer:
o Aurora Serverless v2
o Multi-AZ for HA
Golden Rule:
Each microservice owns its own database.
Synchronous vs Asynchronous APIs on AWS
Synchronous (REST via API Gateway)
35
Example:
POST /orders
Order service:
• Validates input
• Writes to DB
• Publishes event
Asynchronous (Event-Driven)
Use:
• EventBridge (preferred for choreography)
• SNS + SQS
• SQS FIFO (when ordering required)
Flow:
OrderCreatedEvent → EventBridge
→ Payment Service
→ Inventory Service
Why EventBridge?
• Built-in schema registry
• Decoupling
• Filtering rules
Senior tip:
Use events for cross-service communication; REST only for client communication.
Idempotency in AWS APIs
Critical for financial or order APIs.
Implementation:
• Client sends Idempotency-Key
• Store key in:
o DynamoDB with TTL
• Use conditional writes
DynamoDB Example:
PutItem with ConditionExpression
36
attribute_not_exists(idempotencyKey)
Prevents:
• Duplicate orders
• Double charges
Distributed Transactions (Saga on AWS)
Avoid 2-phase commit.
Use:
• Step Functions (Orchestration Saga)
OR
• EventBridge (Choreography Saga)
Example Orchestration:
Step Functions flow:
1. Create Order
2. Reserve Inventory
3. Charge Payment
4. If fail → Compensating step
Benefits:
• Visual workflow
• Built-in retries
• Error handling
Observability & Monitoring
Use:
• CloudWatch Logs
• CloudWatch Metrics
• AWS X-Ray (distributed tracing)
• OpenTelemetry
• CloudWatch Alarms
• AWS Distro for OpenTelemetry
Include:
• Correlation IDs
37
• Structured JSON logs
• Custom metrics
Monitor:
• P95 latency
• Error rate
• Throttling rate
• DLQ depth
Throttling & Protection
Use:
• API Gateway throttling
• Usage plans
• AWS WAF
• Shield (DDoS protection)
• Rate limits per API key
Protect downstream:
• SQS buffer
• Circuit breaker (Resilience4j)
• Auto scaling policies
CI/CD & API Governance
Use:
• AWS CodePipeline
• CodeBuild
• CDK / CloudFormation / Terraform
API management best practices:
• OpenAPI stored in repo
• Contract testing
• Canary deployments
• Blue/Green with CodeDeploy
• API version lifecycle
38
Scaling Considerations
Horizontal scaling:
• Lambda concurrency
• ECS auto scaling
• DynamoDB auto scaling
Decoupling:
• SQS buffers to smooth spikes
Multi-region:
• Route53 latency routing
• DynamoDB Global Tables
• Active-active APIs
🏗 Multi-Account Strategy (Enterprise)
Use AWS Organizations:
• Dev Account
• QA Account
• Prod Account
• Shared Services Account
API exposure:
• Cross-account IAM roles
• PrivateLink for internal APIs
Interview-Ready Closing Statement
“In AWS-based microservices API design, I use API Gateway as a secure entry point, deploy
services on Lambda or ECS based on workload characteristics, enforce authentication using
Cognito or IAM, and ensure loose coupling through EventBridge or SQS. Each service owns
its data in DynamoDB or Aurora, and I implement idempotency, saga patterns, structured
observability with X-Ray, and CI/CD via infrastructure as code. The design prioritizes
scalability, security, and failure isolation while maintaining long-term evolvability.”