When working with Amazon Application Load Balancer (ALB), many developers encounter the same challenge: the ALB's native path-based routing doesn't support path rewriting. The standard configuration allows routing like:
my-alb-dns.com:80/container-a/* → container-a:8080/*
my-alb-dns.com:80/container-b/* → container-b:8080/*
But what if we need to remove the /container-a/
or /container-b/
prefix before forwarding to the target? This is where developers typically resort to Nginx as a middleware solution.
Before implementing custom solutions, let's examine AWS-native options:
- ALB Rules: While ALB supports path-based routing (since April 2017), it lacks path rewriting capabilities
- Lambda@Edge: Works with CloudFront but introduces complexity and additional costs
- API Gateway: Overkill for simple path rewriting between containers
One elegant solution is to use AWS Lambda as an ALB target for path manipulation:
exports.handler = async (event) => {
const request = event.Records[0].cf.request;
const uri = request.uri;
// Example: Rewrite /container-a/path/to/resource to /path/to/resource
if (uri.startsWith('/container-a/')) {
request.uri = uri.replace('/container-a/', '/');
}
return request;
};
To configure this:
- Create a Lambda function with ALB trigger
- Set the Lambda as target for your ALB path pattern
- Ensure Lambda has proper IAM permissions for ELB
While the Lambda solution works, consider these factors:
Solution | Latency | Cost | Maintenance |
---|---|---|---|
Nginx | Low | Medium (EC2 costs) | Medium |
Lambda | Higher (cold starts) | Low (pay per use) | Low |
While AWS hasn't officially announced path rewriting for ALB, we can anticipate this feature based on:
- Growing developer demand
- Similar features in competitors' products
- ALB's continuous evolution (recently added weighted routing)
For most production scenarios currently, I recommend:
ALB → Nginx (path rewriting) → ECS Containers
Sample Nginx configuration:
location /container-a/ {
proxy_pass http://container-a:8080/;
rewrite ^/container-a/(.*) /$1 break;
}
location /container-b/ {
proxy_pass http://container-b:8080/;
rewrite ^/container-b/(.*) /$1 break;
}
Many developers face this exact scenario when working with Amazon Application Load Balancer:
http://my-alb-dns.com/container-a/api/users → container-a:8080/api/users http://my-alb-dns.com/container-b/api/orders → container-b:8080/api/orders
While this can be achieved with an NGINX reverse proxy (which adds infrastructure complexity), AWS ALB doesn't natively support path rewriting as of 2023.
1. Using ALB Path Patterns with Target Groups:
# Example ALB Listener Rule (AWS CLI format) aws elbv2 create-rule \ --listener-arn arn:aws:elasticloadbalancing:us-east-1:123456789012:listener/app/my-load-balancer/1234567890123456/1234567890123456 \ --priority 10 \ --conditions Field=path-pattern,Values='/container-a/*' \ --actions Type=forward,TargetGroupArn=arn:aws:elasticloadbalancing:us-east-1:123456789012:targetgroup/container-a/1234567890123456
Limitation: This forwards the complete path including '/container-a' to your backend service.
Option 1: API Gateway + ALB Integration
# CloudFormation snippet for API Gateway mapping Resources: ApiMapping: Type: AWS::ApiGatewayV2::ApiMapping Properties: ApiId: !Ref MyHttpApi DomainName: api.example.com Stage: !Ref ProdStage ApiMappingKey: "container-a"
Option 2: Lambda@Edge for Path Rewriting
// Lambda@Edge viewer request handler exports.handler = (event, context, callback) => { const request = event.Records[0].cf.request; // Rewrite /container-a/api/ to /api/ if (request.uri.startsWith('/container-a/')) { request.uri = request.uri.replace('/container-a', ''); } callback(null, request); };
For complex rewriting needs, an EC2 instance or ECS container running NGINX might still be optimal:
# NGINX configuration example server { listen 80; location /container-a/ { proxy_pass http://container-a:8080/; rewrite ^/container-a/(.*) /$1 break; } location /container-b/ { proxy_pass http://container-b:8080/; rewrite ^/container-b/(.*) /$1 break; } }
Based on AWS's history of gradually adding ALB features like:
- Host-based routing (2017)
- Weighted target groups (2019)
- HTTP/2 and gRPC support (2020)
Native path rewriting functionality may eventually arrive. Watch the ALB release notes for updates.