1. Pengenalan API Gateway
Amazon API Gateway adalah layanan fully managed yang memungkinkan developer untuk membuat, mempublish, memelihara, memantau, dan mengamankan API pada skala berapa pun. API Gateway bertindak sebagai "front door" bagi aplikasi untuk mengakses backend β baik itu Lambda functions, EC2 instances, ECS services, atau layanan AWS lainnya.
API Gateway menangani semua tugas yang terkait dengan menerima dan memproses hingga ratusan ribu panggilan API secara simultan β termasuk traffic management, authorization, access control, monitoring, dan API version management.
Mengapa API Gateway Penting?
| Fitur | Penjelasan |
|---|---|
| Centralized Entry Point | Satu endpoint untuk semua API β konsisten, mudah dikelola |
| Authentication | Integrasi dengan Cognito, IAM, Lambda Authorizer, OIDC |
| Throttling | Rate limiting per client, per API, per method |
| Caching | Response caching built-in untuk mengurangi beban backend |
| Monitoring | CloudWatch integration untuk metrics dan logging |
| Transformations | Request/response transformation dan mapping |
| WebSocket | Support untuk real-time bidirectional communication |
| Cost | Pay-per-request β tidak ada biaya minimum atau commitment |
ββββββββββββ βββββββββββββββββββββββββββββββββββββββββββββββ
β β β AWS API GATEWAY β
β Client ββββββΊβ βββββββββββ ββββββββββββ ββββββββββββββββ β
β (Mobile/ β β β Auth & β β Throttle β β Transform β β
β Web/ βββββββ β Authorizeβ β & Cache β β & Mapping β β
β IoT) β β βββββββββββ ββββββββββββ ββββββββββββββββ β
ββββββββββββ ββββββββββββββββββββ¬βββββββββββββββββββββββββββ
β
βββββββββββββββββΌββββββββββββββββ
β β β
βΌ βΌ βΌ
ββββββββββββ ββββββββββββ ββββββββββββββββ
β Lambda β β ECS β β HTTP β
β Function β β Service β β Endpoint β
ββββββββββββ ββββββββββββ ββββββββββββββββ
API Gateway + Lambda adalah kombinasi serverless paling populer di AWS. Anda tidak perlu mengelola server sama sekali β API Gateway menangani routing dan Lambda mengeksekusi logic. Bayar hanya ketika ada request.
2. REST API vs HTTP API
API Gateway menyediakan dua jenis API: REST API (API Gateway v1) dan HTTP API (API Gateway v2). Memahami perbedaan keduanya sangat penting untuk memilih jenis yang tepat untuk use case Anda.
Perbandingan REST API vs HTTP API
| Fitur | REST API | HTTP API |
|---|---|---|
| Harga | π΄ $3.50 per juta request | π’ $1.00 per juta request |
| Latency | π‘ Sedang | π’ Rendah (~60% lebih cepat) |
| Caching | π’ Built-in | π΄ Tidak ada |
| WAF Integration | π’ Ya | π‘ Terbatas |
| Request Validation | π’ Ya | π΄ Tidak |
| Usage Plans & API Keys | π’ Ya | π΄ Tidak |
| Transformations | π’ VTL Mapping Templates | π‘ Terbatas |
| JWT Authorizer | π΄ Tidak | π’ Built-in |
| Lambda Authorizer | π’ Ya | π’ Ya |
| Private API | π’ Ya | π΄ Tidak |
| WebSocket | π΄ Tidak | π’ Ya |
Gunakan HTTP API untuk use case sederhana yang membutuhkan performa tinggi dan harga rendah. Gunakan REST API ketika Anda butuh fitur lanjutan seperti caching, request validation, WAF, atau private API.
3. Membuat REST API
Membuat REST API di API Gateway melibatkan beberapa langkah: membuat API, mendefinisikan resource dan method, mengintegrasikan dengan backend, dan mendeploy.
Membuat API dengan AWS CLI
# Membuat REST API baru API_ID=$(aws apigateway create-rest-api \ --name "My API" \ --description "My first API Gateway" \ --endpoint-configuration types=REGIONAL \ --query 'id' --output text) echo "API ID: $API_ID" # Dapatkan root resource ID ROOT_ID=$(aws apigateway get-resources \ --rest-api-id $API_ID \ --query 'items[0].id' --output text) # Membuat resource /users USERS_ID=$(aws apigateway create-resource \ --rest-api-id $API_ID \ --parent-id $ROOT_ID \ --path-part "users" \ --query 'id' --output text) # Membuat GET method pada /users aws apigateway put-method \ --rest-api-id $API_ID \ --resource-id $USERS_ID \ --http-method GET \ --authorization-type NONE # Membuat POST method pada /users aws apigateway put-method \ --rest-api-id $API_ID \ --resource-id $USERS_ID \ --http-method POST \ --authorization-type NONE
Lambda Integration
# Integrasi GET /users dengan Lambda function
aws apigateway put-integration \
--rest-api-id $API_ID \
--resource-id $USERS_ID \
--http-method GET \
--type AWS_PROXY \
--integration-http-method POST \
--uri "arn:aws:apigateway:ap-southeast-1:lambda:path/2015-03-31/functions/arn:aws:lambda:ap-southeast-1:123456789:function:getUsers/invocations"
# Memberikan permission agar API Gateway bisa invoke Lambda
aws lambda add-permission \
--function-name getUsers \
--statement-id apigateway-invoke \
--action lambda:InvokeFunction \
--principal apigateway.amazonaws.com \
--source-arn "arn:aws:execute-api:ap-southeast-1:123456789:${API_ID}/*/GET/users"
Mendeploy API
# Membuat deployment baru
aws apigateway create-deployment \
--rest-api-id $API_ID \
--stage-name prod \
--stage-description "Production stage" \
--description "Initial deployment"
# Endpoint sekarang tersedia di:
# https://${API_ID}.execute-api.ap-southeast-1.amazonaws.com/prod/users
# Menggunakan AWS SAM (lebih mudah untuk serverless)
# template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Globals:
Api:
Cors:
AllowMethods: "'GET,POST,PUT,DELETE,OPTIONS'"
AllowHeaders: "'Content-Type,Authorization'"
AllowOrigin: "'*'"
Resources:
MyApi:
Type: AWS::Serverless::Api
Properties:
StageName: prod
Auth:
DefaultAuthorizer: CognitoAuthorizer
Authorizers:
CognitoAuthorizer:
UserPoolArn: !GetAtt UserPool.Arn
GetUsersFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: src/
Handler: users.getUsers
Runtime: nodejs18.x
Events:
GetUsers:
Type: Api
Properties:
RestApiId: !Ref MyApi
Path: /users
Method: get
4. Stages & Deployments
Stage di API Gateway adalah snapshot dari API Anda pada titik waktu tertentu. Setiap stage memiliki URL endpoint sendiri dan konfigurasi terpisah untuk throttling, caching, logging, dan environment variables.
Common Stage Patterns
| Stage | Penggunaan |
|---|---|
| dev | Development β aktif, bisa diubah kapan saja |
| staging | Pre-production β mirror production untuk testing |
| prod | Production β stabil, dilindungi oleh throttle dan auth |
| v1, v2 | Versioning β bisa menjalankan versi berbeda secara paralel |
Stage Variables
Stage variables memungkinkan Anda menggunakan nilai yang berbeda per stage β berguna untuk mengarahkan ke backend yang berbeda (misalnya database dev vs production).
# Set stage variables
aws apigateway create-deployment \
--rest-api-id $API_ID \
--stage-name dev
aws apigateway update-stage \
--rest-api-id $API_ID \
--stage-name dev \
--patch-operations \
op=replace,path=/variables/backendUrl,value="https://dev-api.example.com" \
op=replace,path=/variables/lambdaAlias,value="dev"
# Production stage dengan stage variables berbeda
aws apigateway create-deployment \
--rest-api-id $API_ID \
--stage-name prod
aws apigateway update-stage \
--rest-api-id $API_ID \
--stage-name prod \
--patch-operations \
op=replace,path=/variables/backendUrl,value="https://prod-api.example.com" \
op=replace,path=/variables/lambdaAlias,value="prod"
# Menggunakan stage variables di integration URI:
# arn:aws:apigateway:region:lambda:path/2015-03-31/functions/
# arn:aws:lambda:region:account:function:${stageVariables.lambdaAlias}/invocations
Canary Deployment
Canary deployment memungkinkan Anda mengarahkan sebagian kecil traffic ke versi baru API β berguna untuk testing di production sebelum full rollout.
# Membuat canary release β 10% traffic ke versi baru
aws apigateway update-stage \
--rest-api-id $API_ID \
--stage-name prod \
--patch-operations \
op=replace,path=/canarySettings/percentTraffic,value="10" \
op=replace,path=/canarySettings/deploymentId,value="$NEW_DEPLOYMENT_ID"
# Monitor canary performance via CloudWatch
# Jika sukses, tingkatkan persentase secara bertahap
# Promote canary ke 100% (menjadi deployment utama)
aws apigateway update-stage \
--rest-api-id $API_ID \
--stage-name prod \
--patch-operations \
op=replace,path=/deploymentId,value="$NEW_DEPLOYMENT_ID"
5. Throttling & Rate Limiting
API Gateway menyediakan throttling built-in untuk melindungi backend dari traffic berlebihan. Throttling bekerja di beberapa level: account-wide, per stage, dan per method.
Throttling Levels
| Level | Default | Penjelasan |
|---|---|---|
| Account-wide | 10,000 req/detik | Limit untuk semua API di satu region |
| Per Stage | 10,000 req/detik | Limit per stage (dev, prod, dll) |
| Per Method | Mengikuti stage | Limit per HTTP method per resource |
| Usage Plans | Custom per client | Limit per API key / client |
Konfigurasi Throttling
# Set stage-level throttle
aws apigateway update-stage \
--rest-api-id $API_ID \
--stage-name prod \
--patch-operations \
op=replace,path=/throttling/rateLimit,value="5000" \
op=replace,path=/throttling/burstLimit,value="2000"
# Set method-level throttle (lebih ketat untuk POST)
aws apigateway update-stage \
--rest-api-id $API_ID \
--stage-name prod \
--patch-operations \
op=replace,path=/~1users/POST/throttling/rateLimit,value="100" \
op=replace,path=/~1users/POST/throttling/burstLimit,value="200"
Usage Plans & API Keys
Usage plans memungkinkan Anda memberikan limit yang berbeda ke client yang berbeda. Setiap client mendapatkan API key yang terkait dengan usage plan tertentu.
# Membuat usage plan PLAN_ID=$(aws apigateway create-usage-plan \ --name "Basic Plan" \ --description "Basic tier - 1000 req/day" \ --throttle rateLimit=10,burstLimit=20 \ --quota limit=1000,period=DAY \ --api-stages apiId=$API_ID,stage=prod \ --query 'id' --output text) # Membuat API key KEY_ID=$(aws apigateway create-api-key \ --name "Client App Key" \ --enabled \ --query 'id' --output text) # Mengaitkan API key dengan usage plan aws apigateway create-usage-plan-key \ --usage-plan-id $PLAN_ID \ --key-id $KEY_ID \ --key-type API_KEY # Client menggunakan API key di header: # x-api-key: YOUR_API_KEY_VALUE
6. Authorization & Authentication
API Gateway mendukung beberapa metode authentication dan authorization. Memilih metode yang tepat sangat penting untuk keamanan API Anda.
Jenis Authorization
| Tipe | Penjelasan | Use Case |
|---|---|---|
| IAM Auth | Gunakan AWS IAM policies untuk authorize request | Internal AWS services, cross-account |
| Cognito User Pools | JWT token dari Cognito User Pool | User-facing apps (mobile, web) |
| Lambda Authorizer | Custom Lambda function yang validate token | Custom auth logic, 3rd party JWT |
| JWT Authorizer | Validate JWT dari OIDC/IdP (HTTP API only) | Auth0, Okta, custom IdP |
Cognito Authorizer
# Membuat Cognito User Pool
USER_POOL_ID=$(aws cognito-idp create-user-pool \
--pool-name "MyAppUsers" \
--policies 'PasswordPolicy={MinimumLength=8,RequireUppercase=true,RequireNumbers=true}' \
--auto-verified-attributes email \
--query 'UserPool.Id' --output text)
# Membuat Cognito Authorizer di API Gateway
aws apigateway update-authorizer \
--rest-api-id $API_ID \
--authorizer-id $AUTH_ID \
--patch-operations \
op=replace,path=/identitySource,value="method.request.header.Authorization" \
op=replace,path=/type,value="COGNITO_USER_POOLS" \
op=replace,path=/providerARNs,value="[\"arn:aws:cognito-idp:ap-southeast-1:123456789:userpool/$USER_POOL_ID\"]"
# Set authorizer pada method
aws apigateway update-method \
--rest-api-id $API_ID \
--resource-id $USERS_ID \
--http-method GET \
--patch-operations \
op=replace,path=/authorizationType,value="COGNITO_USER_POOLS" \
op=replace,path=/authorizerId,value="$AUTH_ID"
Lambda Authorizer
// Lambda Authorizer function
exports.handler = async (event) => {
const token = event.authorizationToken; // "Bearer xxxxx"
try {
// Validasi JWT token
const decoded = jwt.verify(
token.replace('Bearer ', ''),
process.env.JWT_SECRET
);
// Return IAM policy yang mengizinkan akses
return generatePolicy(decoded.sub, 'Allow', event.methodArn);
} catch (err) {
// Token tidak valid β tolak akses
return generatePolicy('user', 'Deny', event.methodArn);
}
};
function generatePolicy(principalId, effect, resource) {
return {
principalId,
policyDocument: {
Version: '2012-10-17',
Statement: [{
Action: 'execute-api:Invoke',
Effect: effect,
Resource: resource
}]
},
// Context bisa diakses di Lambda backend
context: {
userId: principalId,
role: 'user'
}
};
}
7. Request/Response Mapping
API Gateway mendukung transformasi data request dan response menggunakan VTL (Velocity Template Language) mapping templates. Ini berguna untuk mengubah format data antara client dan backend.
Request Mapping Template
## Contoh VTL Request Mapping Template
## Mengubah query parameter menjadi Lambda event yang rapi
#set($inputRoot = $input.path('$'))
{
"userId": "$input.params('user-id')",
"queryString": "$input.params('q')",
"requestId": "$context.requestId",
"sourceIp": "$context.identity.sourceIp",
"timestamp": "$context.requestTime",
"headers": {
#foreach($header in $input.params().header.keySet())
"$header": "$input.params().header.get($header)"#if($foreach.hasNext),#end
#end
}
}
Response Mapping Template
## Response mapping β wrap Lambda response ke format API standar
#set($inputRoot = $input.path('$'))
{
"status": "success",
"data": $input.json('$'),
"metadata": {
"requestId": "$context.requestId",
"timestamp": "$context.requestTime",
"latency": "$context.integrationLatency"
}
}
## Error response mapping
#if($input.path('$.errorMessage').contains("not found"))
#set($context.responseOverride.status = 404)
{
"status": "error",
"code": "RESOURCE_NOT_FOUND",
"message": "$input.path('$.errorMessage')"
}
#else
#set($context.responseOverride.status = 500)
{
"status": "error",
"code": "INTERNAL_ERROR",
"message": "An unexpected error occurred"
}
#end
8. Custom Domain Names
Secara default, API Gateway menggunakan URL yang tidak mudah diingat: https://abc123xyz.execute-api.ap-southeast-1.amazonaws.com/prod. Anda bisa menggunakan custom domain name untuk URL yang lebih profesional.
Setup Custom Domain
# 1. Buat/minta SSL certificate di ACM (harus di us-east-1 untuk edge-optimized)
aws acm request-certificate \
--domain-name "api.example.com" \
--validation-method DNS \
--region us-east-1
# 2. Buat custom domain name di API Gateway
aws apigateway create-domain-name \
--domain-name "api.example.com" \
--regional-certificate-arn "arn:aws:acm:ap-southeast-1:123456789:certificate/xxx" \
--endpoint-configuration types=REGIONAL \
--security-policy TLS_1_2
# 3. Buat base path mapping
aws apigateway create-base-path-mapping \
--domain-name "api.example.com" \
--base-path "v1" \
--rest-api-id $API_ID \
--stage prod
# 4. Buat DNS record di Route 53
aws route53 change-resource-record-sets \
--hosted-zone-id Z123456789 \
--change-batch '{
"Changes": [{
"Action": "CREATE",
"ResourceRecordSet": {
"Name": "api.example.com",
"Type": "A",
"AliasTarget": {
"HostedZoneId": "Z2FDTNDATAQYW2",
"DNSName": "d-xxx.execute-api.ap-southeast-1.amazonaws.com",
"EvaluateTargetHealth": false
}
}
}]
}'
9. Caching
REST API di API Gateway mendukung built-in caching yang menyimpan response untuk periode waktu tertentu. Ini mengurangi beban backend dan mempercepat response time untuk request yang berulang.
Konfigurasi Cache
# Enable cache pada stage
aws apigateway update-stage \
--rest-api-id $API_ID \
--stage-name prod \
--patch-operations \
op=replace,path=/cacheClusterEnabled,value=true \
op=replace,path=/cacheClusterSize,value="0.5" \
op=replace,path=/~1users/GET/caching/enabled,value=true \
op=replace,path=/~1users/GET/caching/ttlInSeconds,value="300"
# Cache sizes: 0.5, 1.6, 6.1, 13.5, 28.4, 58.2, 118, 237 GB
# Invalidate cache (setelah data berubah)
aws apigateway flush-stage-cache \
--rest-api-id $API_ID \
--stage-name prod
Cache menghasilkan biaya tambahan. Gunakan cache hanya untuk endpoint yang sering diakses dengan data yang jarang berubah (seperti konfigurasi, daftar produk, dll). Jangan cache data user-specific tanpa cache key yang tepat.
10. Best Practices
API Design
- Gunakan HTTP API untuk use case sederhana β lebih murah dan lebih cepat dari REST API
- Versioning β Gunakan path versioning (
/v1/users) atau header versioning - Consistent naming β Gunakan plural nouns untuk resource, lowercase, dash-case
- Request validation β Validasi input di API Gateway sebelum ke backend (REST API)
- CORS β Konfigurasi CORS headers yang tepat, jangan wildcard di production
Security
- Selalu gunakan authorizer β minimal Cognito atau Lambda authorizer untuk setiap endpoint
- WAF β Deploy AWS WAF di depan API Gateway untuk melindungi dari OWASP Top 10
- Throttling β Set rate limit yang reasonable untuk mencegah abuse
- API Keys β Gunakan API keys untuk public API dengan usage plans
- mTLS β Untuk B2B API, pertimbangkan mutual TLS authentication
Performance
- Caching β Enable cache untuk GET endpoint yang sering diakses
- Compression β Enable response compression untuk mengurangi bandwidth
- Regional endpoints β Gunakan regional endpoint untuk client yang dekat, edge-optimized untuk global
- Binary media types β Daftarkan binary content types untuk file upload/download
Monitoring
# Enable access logging
aws apigateway update-stage \
--rest-api-id $API_ID \
--stage-name prod \
--patch-operations \
op=replace,path=/accessLogSettings/destinationArn,value="arn:aws:logs:ap-southeast-1:123456789:log-group:api-gateway-logs" \
op=replace,path=/methodSettings/*/*/loggingLevel,value="INFO" \
op=replace,path=/methodSettings/*/*/metricsEnabled,value=true \
op=replace,path=/methodSettings/*/*/dataTraceEnabled,value=true"
# CloudWatch metrics tersedia:
# - 4XXError: Client errors (bad request, unauthorized, dll)
# - 5XXError: Server errors (backend failures)
# - Latency: Total response time (gateway + backend)
# - IntegrationLatency: Waktu backend processing
# - Count: Jumlah total request
# - CacheHitCount / CacheMissCount