Based on the DVA-C02 exam guideReport an error
When Amazon API Gateway first appeared in 2015, the ways to build a serverless API were to run Flask or Express on EC2, or to use Elastic Beanstalk. API Gateway started out in the role of "a managed service that exposes a Lambda function as an HTTP endpoint", but over time it grew into a complete API management platform with authentication, caching, traffic control, and monitoring bolted on.
Today we dissect the internal structure of the REST API completely. From the moment a client sends an HTTP request, through the invocation of Lambda, to the response coming back — once you understand what every layer along that path does, 70% of the exam questions solve themselves.
Since 2022, Lambda has had Function URLs. You can attach an HTTPS endpoint directly to a Lambda function without API Gateway. So why use API Gateway at all?
| Feature | Function URL | API Gateway HTTP API | API Gateway REST API |
|---|---|---|---|
| Cost | Free (Lambda charges only) | $1/million calls | $3.5/million calls |
| Routing | Single function | Different function per path | Different function per path |
| Auth | NONE / AWS_IAM | JWT / Lambda / IAM | Lambda / Cognito / IAM |
| Caching | ❌ | ❌ | ✅ |
| API keys & usage plans | ❌ | ❌ | ✅ |
| Request validation | ❌ | ❌ | ✅ (JSON Schema based) |
| WAF integration | ❌ | ❌ | ✅ |
| VTL transformation | ❌ | ❌ | ✅ |
| X-Ray | ❌ | ❌ | ✅ |
| Response Streaming | ✅ | ❌ | ❌ |
| WebSocket | ❌ | ❌ | Separate WebSocket API |
Selection criteria: Single Lambda + simple HTTP exposure → Function URL. Complex routing, auth, caching, and usage limits needed → REST API. Cost-sensitive, simple Lambda/HTTP proxy → HTTP API.
💡 Related theory: API Gateway is a combination of the Message Router + Message Filter from Enterprise Integration Patterns (EIP, Gregor Hohpe 2003) and the API Gateway Pattern (Sam Newman, "Building Microservices" 2015). In a microservices architecture, the API Gateway pattern lets external clients reach dozens of services through a single entry point without needing to know each one directly. Netflix's Zuul, Kong, Nginx Plus, and AWS API Gateway are all implementations of this pattern.
A REST API is a tree structure.
API (MyShopAPI)
└── Resource /products
├── GET → Integration (Lambda: ListProducts)
│ ├── Integration Request (request transformation)
│ └── Integration Response (response transformation)
├── POST → Integration (Lambda: CreateProduct)
└── /products/{productId}
├── GET → Integration (Lambda: GetProduct)
├── PUT → Integration (Lambda: UpdateProduct)
└── DELETE → Integration (Lambda: DeleteProduct)
Resource: The URL path. Path parameters are declared with {} curly braces.
Method: GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS.
Integration: The backend a method calls. Lambda, HTTP, AWS service, Mock.
Stage: A deployment environment. dev, staging, prod.
Deployment: A snapshot of API changes. It must be attached to a stage to take effect.
⚠️ Trap: After changing an API, you must create a deployment and attach it to a stage for the change to apply. If you only hit "Save" in the console and skip the deployment, clients still see the previous version of the API.
Client request (HTTPS)
│
▼
[1. Endpoint receipt]
Edge-Optimized: TLS termination at a CloudFront PoP
Regional: directly to the regional API Gateway
Private: via a VPC Interface Endpoint
│
▼
[2. Method Request]
- Authentication (IAM SigV4, Lambda Authorizer, Cognito)
- Validation of path parameters, headers, query string
- Request model (JSON Schema) validation
On failure → immediately returns 400/401/403
│
▼
[3. Integration Request]
- Transform the request with a VTL mapping template
- Call the Lambda / HTTP endpoint / AWS service
│
▼
[4. Backend processing]
- Lambda execution
- HTTP endpoint response
- DynamoDB response, etc.
│
▼
[5. Integration Response]
- Backend response → transformed with a VTL mapping template
- With Lambda Proxy, passed through as-is with no transformation
│
▼
[6. Method Response]
- Sets the HTTP status code, headers, and response model
- Delivers the final response to the client
Once you understand these six stages, API Gateway troubleshooting becomes easy.
Edge-Optimized: Terminates TLS at CloudFront's 600+ PoPs and forwards the request over the backbone network. Suitable for public APIs with many global users. Note that this is an AWS-managed CloudFront that doesn't appear in your actual CloudFront console. If you need custom CloudFront configuration, use Regional + a separate CloudFront.
Regional: Clients in the same region connect directly. Advantageous when calling an API in the same region from EC2 or Lambda. You can attach your own CloudFront to add caching and WAF.
Private: Accessible only through an Interface Endpoint (PrivateLink) inside a VPC. Absolutely unreachable from the internet. Suitable for internal microservice APIs and data pipeline APIs.
| Endpoint | CloudFront | Custom domain ACM location | Use case |
|---|---|---|---|
| Edge-Optimized | AWS-managed | us-east-1 required | Global public API |
| Regional | Optional (your own) | Each region | In-region services, mobile backends |
| Private | None | Each region | Internal VPC APIs |
⚠️ Trap: The ACM certificate for an Edge-Optimized custom domain must be issued in us-east-1. This is because CloudFront only references ACM in us-east-1. In a "my domain doesn't work" scenario, a common cause is a certificate issued in a region other than us-east-1. Regional endpoints may use certificates issued in each region's own ACM.
A stage is more than just distinguishing "dev/staging/prod". Through stage variables, the same API definition can route to different backends.
API integration URI:
arn:aws:lambda:ap-northeast-2:123:function:OrderAPI:${stageVariables.lambdaAlias}
dev stage: lambdaAlias = dev → OrderAPI:dev (alias)
prod stage: lambdaAlias = prod → OrderAPI:prod (alias)
Stage variable usage patterns:
${stageVariables.backendUrl})# Set stage variables
aws apigateway create-stage \
--rest-api-id abc123 \
--stage-name prod \
--variables 'lambdaAlias=prod,backendUrl=https://api.mycompany.com'🔍 Going deeper: Stage variables are environment variables at the API Gateway level. They are a different layer from a Lambda function's environment variables. Lambda environment variables are exposed to your code at function execution time, while stage variables are substituted when API Gateway constructs the integration URI. Use both together and you get a structure where API Gateway → Lambda integration calls a different function per stage, and each function internally manages additional configuration via its own environment variables.
| Item | REST API | HTTP API | WebSocket API |
|---|---|---|---|
| Cost | $3.5/million | $1/million | $1/million messages + connection time |
| Latency | Moderate | Low | - |
| Communication direction | Request-response | Request-response | Bidirectional |
| Lambda Proxy | ✅ | ✅ | Per route |
| Lambda Authorizer | ✅ | ✅ | ✅ |
| JWT Authorizer | Via Lambda | ✅ Native | ❌ |
| Cognito Authorizer | ✅ | Use JWT instead | ❌ |
| IAM (SigV4) | ✅ | ✅ | ✅ |
| API keys & usage plans | ✅ | ❌ | ❌ |
| Response caching | ✅ | ❌ | - |
| Request validation (models) | ✅ | ❌ | ❌ |
| VTL mapping templates | ✅ | ❌ | ❌ |
| Direct AWS service integration | ✅ | ❌ | ❌ |
| WAF integration | ✅ | CloudFront required | ❌ |
| X-Ray tracing | ✅ | ❌ | ❌ |
| Edge-Optimized | ✅ | ❌ | ❌ |
| VPC Link (ALB) | NLB only | ALB/NLB/Cloud Map | ❌ |
| Automatic CORS setup | Manual | ✅ | - |
Exam scenario keyword → choice:
Route 53 A record (Alias)
api.mycompany.com → API Gateway Custom Domain
│
▼
API Gateway Custom Domain Name
+ ACM certificate (HTTPS TLS)
│
▼ Base Path Mapping
/v1 → REST API "MyAPI" stage "prod"
/v2 → REST API "MyAPI-v2" stage "prod"
/internal → REST API "InternalAPI" stage "prod"
# Create a custom domain (Regional endpoint)
aws apigateway create-domain-name \
--domain-name api.mycompany.com \
--endpoint-configuration types=REGIONAL \
--regional-certificate-arn arn:aws:acm:ap-northeast-2:123:certificate/abc
# Base Path Mapping (route multiple APIs through one domain)
aws apigateway create-base-path-mapping \
--domain-name api.mycompany.com \
--rest-api-id abc123 \
--stage prod \
--base-path v1Separately from the canary on a Lambda alias, you can enable a canary on the REST API stage itself.
# Configure a canary on the stage (only 10% of traffic to the new deployment)
aws apigateway update-stage \
--rest-api-id abc123 \
--stage-name prod \
--patch-operations \
'op=replace,path=/canarySettings/percentTraffic,value=10' \
'op=replace,path=/canarySettings/deploymentId,value=new-deploy-id'
# Promote the canary (to 100%)
aws apigateway update-stage \
--rest-api-id abc123 \
--stage-name prod \
--patch-operations 'op=replace,path=/canarySettings/percentTraffic,value=0'💡 Related theory: When you use API Gateway's canary deployment together with traffic splitting on a Lambda alias, you get two layers of safety. Combining an API Gateway canary (at the deployment-version level) with a Lambda alias canary (at the function-version level) minimizes deployment risk. This is in line with Netflix's "Chaos Engineering" principle — verify a system's robustness through controlled risk.
When managing API definitions as code or sharing them across teams, use the OpenAPI 3.0 format.
# openapi.yaml
openapi: "3.0.1"
info:
title: "ProductAPI"
version: "1.0"
paths:
/products:
get:
summary: "List products"
x-amazon-apigateway-integration:
type: aws_proxy
httpMethod: POST
uri: "arn:aws:apigateway:ap-northeast-2:lambda:path/2015-03-31/functions/arn:aws:lambda:ap-northeast-2:123:function:ListProducts/invocations"
payloadFormatVersion: "1.0"
responses:
"200":
description: "Success"# Import an API from an OpenAPI definition
aws apigateway import-rest-api \
--body file://openapi.yaml \
--region ap-northeast-2
# Update an existing API (merge mode)
aws apigateway put-rest-api \
--rest-api-id abc123 \
--mode merge \
--body file://openapi.yaml| API type | First 300M calls | Beyond |
|---|---|---|
| REST API | $3.50/million | $1.51/million |
| HTTP API | $1.00/million | $0.90/million |
| WebSocket | $1.00/million messages + $0.25/million connection-minutes | - |
| Caching | 0.5GB: $0.020/h ~ 237GB: $3.800/h | - |
Data transfer: the first 10TB/month is $0.09/GB, with tiered discounts after that.
📚 Case study: In 2019, Slack adopted API Gateway HTTP API (in its early release) and dramatically cut the cost of receiving webhooks. On short webhook requests running thousands per second, a 70% reduction versus REST API was verified. However, those internal Slack APIs that need usage tracking still use REST API — because API keys and usage plans are not available on HTTP API.
An API Gateway REST API is a 6-stage pipeline that receives an HTTP request, authenticates it, validates it, transforms it, calls the backend, and transforms the response on the way back. The endpoint type determines the traffic path, the stage is the per-environment deployment unit, and stage variables are the mechanism for flexibly connecting a single API definition to multiple environments. The three API types — REST, HTTP, WebSocket — have clear trade-offs in features and cost, and you simply choose based on your requirements.
In the next article, we dig into the heart of API Gateway integrations: Lambda Proxy integration, VTL mapping templates, and direct AWS service integration.
Click a choice to reveal the answer and explanation.
Question 1
You created a stage on an API Gateway REST API, but your changes are not reflected to clients. What is the cause?
Question 2
When setting up a custom domain on an Edge-Optimized API Gateway, where must the ACM certificate be issued?
Question 3
You provide an API to partner companies and need to set a different call limit for each partner. Which API Gateway feature should you use?
Question 4
Which API type lets you integrate WAF (Web Application Firewall) directly with API Gateway?
Question 5
Which of the following is NOT an appropriate use case for an API Gateway stage variable?
Question 6
A team is evaluating migrating from REST API to HTTP API. Which functional requirement makes migration impossible?
Question 7
Among API Gateway REST API endpoint types, which is accessible only from inside a VPC?