Skip to content

aws-samples/sample-api-migration

Zero-Downtime API Migration with User-Aware Traffic Splitting

⚠️ DISCLAIMER: This is sample code intended for demonstration only. Review and adapt security configurations before deploying to your environments.

This repository provides sample implementations for the patterns described in the AWS Blog Post: Zero-Downtime API Migration with User-Aware Traffic Splitting.

Note: This demo uses HTTP Basic Authentication for simplicity. In production environments, implement robust authentication using Amazon Cognito, OAuth 2.0, or AWS IAM authentication.

Key Concepts

Strangler Fig Pattern: An architectural pattern for gradually migrating from legacy systems to modern implementations by incrementally routing traffic to new components while the old system continues running. Named after the strangler fig tree that grows around and eventually replaces its host tree.

User-Aware Routing: A traffic distribution strategy that ensures each user is consistently routed to the same API version throughout their session, preventing data inconsistencies.

Key Features

  • Zero-downtime migration with no service interruptions
  • User-aware routing using deterministic hash-based assignment
  • Gradual rollout with percentage-based traffic control
  • Real-time adjustments without function redeployment
  • Instant rollback capability for risk mitigation

Architecture

The solution uses:

  • Amazon CloudFront Distribution - AWS's content delivery network (CDN) that routes requests globally
  • Amazon CloudFront Function - Lightweight JavaScript code that runs at edge locations to make routing decisions
  • Amazon CloudFront Key Value Store - A low-latency data store that holds routing configuration and API endpoint URLs
  • Amazon API Gateway - AWS's managed API service; we deploy multiple endpoints (A, B1, B2) representing old and new APIs
  • AWS CDK - Infrastructure as Code toolkit that lets you define cloud resources using TypeScript

Migration Phases

Phase 0 - Initial State: Legacy API (A) serves 100% of traffic Phase 1 - Establish the Fig: Deploy CDN layer and new APIs with 0% traffic routing Phase 2 - Gradual Strangulation: Incrementally shift traffic from 0% to 100% Phase 3 - Complete Migration: Route 100% traffic to new APIs, decommission legacy

User-Aware Routing

The CloudFront function ensures users have a consistent experience by always sending the same user to the same API version:

  • Extracts username from HTTP Authorization header
  • Uses a hash function (a mathematical algorithm that converts the username into a consistent number)
  • This number determines which API version the user should access
  • The same username always produces the same number, ensuring consistent routing throughout the user's session

Prerequisites

Before you begin, ensure you have the following tools installed:

  • AWS CLI - Command-line tool for interacting with AWS services. Installation guide
    • Configure with appropriate permissions for CloudFront, API Gateway, and IAM
  • Node.js and npm - JavaScript runtime and package manager (version 18 or higher). Download
  • AWS CDK CLI - Infrastructure as Code toolkit for defining cloud resources
  • jq - Command-line JSON processor for parsing deployment outputs. Installation guide

Deployment

  1. Install dependencies:

    npm install
  2. Deploy the CDK stack and save outputs:

    cdk deploy --outputs-file outputs.json
  3. Configure the Key Value Store with API endpoints:

    ./scripts/update-kvs.sh
  4. Set traffic control percentage to route to legacy API:

    ./scripts/set-traffic-shift.sh 0 10

Testing

Test API Response

After deployment, test the CloudFront endpoint:

# Get the CloudFront domain from outputs.json
CLOUDFRONT_DOMAIN=$(cat outputs.json | jq -r '.DemoStack.CLOUDFRONTDOMAINNAME')
curl -L -H "Authorization:Basic $(echo -n test:test | base64)" https://$CLOUDFRONT_DOMAIN

Send Multiple Test Requests Asynchronously

./scripts/send-test-requests.sh 5   # Send multiple requests in 5 seconds
./scripts/send-test-requests.sh 3600  # Send multiple requests in 1 hour

Gradual Traffic Migration

# Start with 0% traffic to new APIs
./scripts/set-traffic-shift.sh 0 10

# Gradually increase to 25% over 60 seconds
./scripts/set-traffic-shift.sh 25 60

# Jump to 100% for complete migration over 60 seconds
./scripts/set-traffic-shift.sh 100 60

# Rollback to 0% if issues arise
./scripts/set-traffic-shift.sh 0 30

How It Works

CloudFront Function Benefits

  1. Traffic Control: Control the percentage of traffic being redirected to new APIs
  2. Dynamic Routing: Route traffic to specific APIs (B1, B2, etc.) based on URL patterns
  3. Low Latency: CloudFront Functions execute at edge locations for minimal latency

Key Value Store Configuration

The CloudFront Key Value Store contains:

  • APIGW_A_URL: Original API Gateway endpoint
  • APIGW_B1_URL: New API Gateway endpoint 1
  • APIGW_B2_URL: New API Gateway endpoint 2
  • traffic-split: Percentage of traffic to route to new APIs (0-100)

User-Aware Hash Algorithm

Why user-aware routing? To ensure a consistent experience, users should always be routed to the same API version throughout their session. This prevents mid-session switching that could cause data inconsistencies or confusing behavior.

The function uses a deterministic hash algorithm to consistently assign each user to either the legacy or new API based on their username. The same username always produces the same hash value, ensuring consistent routing:

String.prototype.hashCode = function() {
    var hash = 0, i = 0, len = this.length;
    while ( i < len ) {
        hash  = ((hash << 5) - hash + this.charCodeAt(i++)) << 0;
    }
    return hash + Math.pow(2,31);
};

function isShiftCandidate(username, trafficSplit){
    return username.hashCode() % 100 < trafficSplit ? true : false;
}

Testing Process

  1. Deploy the infrastructure using CDK
  2. Configure the Key Value Store with API endpoints
  3. Access the CloudFront URL to see traffic routing in action
  4. Requests are routed to different API Gateway endpoints based on configuration
  5. Each API returns a unique response: {"message": "Hello from API 1"} or {"message": "Hello from API 2"}

Manual Key Value Store Management

If you need to manually manage the Key Value Store:

  1. Get the Key Value Store ETAG:

    aws cloudfront-keyvaluestore describe-key-value-store --kvs-arn=[KVS_ARN_FROM_OUTPUTS]
  2. Update entries:

    aws cloudfront-keyvaluestore update-keys \
      --kvs-arn=[KVS_ARN_FROM_OUTPUTS] \
      --if-match=[ETAG] \
      --puts '[{"Key": "APIGW_A_URL", "Value": "[API_GATEWAY_1_URL]"},
               {"Key": "APIGW_B1_URL", "Value": "[API_GATEWAY_2_URL]"},
               {"Key": "APIGW_B2_URL", "Value": "[API_GATEWAY_3_URL]"}]'

Project Structure

├── bin/                   # CDK app entry point
├── infra/                 # CDK infrastructure code
├── scripts/               # Deployment and testing scripts
├── cdk.json               # CDK configuration
├── package.json           # Node.js dependencies
└── README.md              # This file

Useful CDK Commands

  • npm run build - Compile TypeScript to JavaScript
  • npm run watch - Watch for changes and compile
  • npx cdk deploy - Deploy the stack to your AWS account/region
  • npx cdk diff - Compare deployed stack with current state
  • npx cdk synth - Emit the synthesized CloudFormation template
  • npx cdk destroy - Remove the deployed stack

Cleanup

To remove all resources:

npx cdk destroy

Security Considerations

When adapting this solution for production use, consider the following:

  1. Authentication: Replace Basic Authentication with Amazon Cognito, OAuth 2.0, or IAM authentication
  2. WAF Integration: Enable AWS WAF on the CloudFront distribution and API Gateway endpoints for protection against common web exploits.
  3. Geo-Restrictions: Configure geographic restrictions if your application has regional compliance requirements
  4. API Gateway Authorization: Implement proper authorization on API Gateway endpoints
  5. Secrets Management: Use AWS Secrets Manager for any sensitive configuration
  6. Monitoring: Enable AWS CloudTrail and Amazon CloudWatch alarms for security monitoring

Further best practices can be found at AWS security best practices

References

Security

1. Authentication Replace Basic Authentication with Amazon Cognito, OAuth 2.0, or IAM authentication

2. WAF Integration Enable AWS WAF on CloudFront distribution and API Gateway endpoints

3. API Gateway Authorization Implement proper authorization on API Gateway endpoints

5. Secrets Management Use AWS Secrets Manager for sensitive configuration

Architecture Patterns

Use CloudFront KeyValueStore and Functions

About

No description, website, or topics provided.

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

No contributors