Blue-green deployments minimize downtime and risk by maintaining two identical production environments (Blue and Green) and switching traffic between them. Here’s how to implement this pattern with React applications:
Core Implementation Strategies
1. DNS-Based Blue-Green Deployment
// deployment-script.js (Route 53 example)
const AWS = require('aws-sdk');
const route53 = new AWS.Route53();
async function switchTraffic({ blueStack, greenStack, domain }) {
const params = {
ChangeBatch: {
Changes: [{
Action: 'UPSERT',
ResourceRecordSet: {
Name: domain,
Type: 'A',
AliasTarget: {
HostedZoneId: greenStack.hostedZoneId,
DNSName: greenStack.distributionDomain,
EvaluateTargetHealth: false
}
}
}]
},
HostedZoneId: blueStack.hostedZoneId
};
await route53.changeResourceRecordSets(params).promise();
console.log(`Traffic switched to Green environment`);
}
2. Load Balancer Approach
# AWS CloudFormation template snippet
Resources:
BlueTargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
Port: 80
Protocol: HTTP
VpcId: !Ref VPC
HealthCheckPath: /health
GreenTargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
Port: 80
Protocol: HTTP
VpcId: !Ref VPC
HealthCheckPath: /health
Listener:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
LoadBalancerArn: !Ref LoadBalancer
Port: 443
Protocol: HTTPS
DefaultActions:
- Type: forward
TargetGroupArn: !Ref BlueTargetGroup
CI/CD Pipeline Integration
3. GitHub Actions Blue-Green Workflow
name: Blue-Green Deployment
on:
push:
branches: [main]
jobs:
deploy-green:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
- name: Build React App
run: npm run build
- name: Deploy to Green Environment
uses: aws-actions/configure-aws-credentials@v2
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-east-1
run: |
aws s3 sync build/ s3://green-bucket --delete
aws cloudfront create-invalidation --distribution-id $GREEN_DISTRIBUTION --paths "/*"
smoke-test:
needs: deploy-green
runs-on: ubuntu-latest
steps:
- run: |
# Run smoke tests against green environment
curl -I https://green.example.com/health
switch-traffic:
needs: smoke-test
runs-on: ubuntu-latest
steps:
- uses: aws-actions/configure-aws-credentials@v2
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-east-1
run: |
# Update Route53 to point to green environment
aws route53 change-resource-record-sets --cli-input-json file://switch-to-green.json
Kubernetes Implementation
4. Kubernetes Blue-Green with Services
# blue-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: react-app-blue
spec:
replicas: 3
selector:
matchLabels:
app: react-app
version: blue
template:
metadata:
labels:
app: react-app
version: blue
spec:
containers:
- name: react-app
image: react-app:1.0.0
ports:
- containerPort: 80
# green-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: react-app-green
spec:
replicas: 3
selector:
matchLabels:
app: react-app
version: green
template:
metadata:
labels:
app: react-app
version: green
spec:
containers:
- name: react-app
image: react-app:1.1.0
ports:
- containerPort: 80
# service.yaml
apiVersion: v1
kind: Service
metadata:
name: react-app
spec:
selector:
app: react-app
version: blue # Initially points to blue
ports:
- protocol: TCP
port: 80
targetPort: 80
5. Kubernetes Traffic Switching
# Switch service to green deployment
kubectl patch service react-app -p '{"spec":{"selector":{"version":"green"}}}'
# Rollback to blue if needed
kubectl patch service react-app -p '{"spec":{"selector":{"version":"blue"}}}'
Advanced Techniques
6. Canary Analysis Before Full Cutover
// Weighted DNS routing for gradual traffic shift
const weights = {
blue: 70,
green: 30
};
async function shiftTraffic(weights) {
const params = {
ChangeBatch: {
Changes: [{
Action: 'UPSERT',
ResourceRecordSet: {
Name: 'app.example.com',
Type: 'CNAME',
TTL: 60,
ResourceRecords: [
{ Value: 'blue-elb.example.com' },
{ Value: 'green-elb.example.com' }
],
Weight: weights.blue
}
}, {
Action: 'UPSERT',
ResourceRecordSet: {
Name: 'app.example.com',
Type: 'CNAME',
TTL: 60,
ResourceRecords: [
{ Value: 'green-elb.example.com' }
],
Weight: weights.green
}
}]
},
HostedZoneId: 'Z2FDTNDATAQYW2'
};
await route53.changeResourceRecordSets(params).promise();
}
7. Database Migration Strategy
// Database versioning approach
async function migrateData() {
// Check which environment is active
const activeEnv = await getActiveEnvironment();
if (activeEnv === 'blue') {
// Migrate data to green database
await migrateDatabase('blue-db', 'green-db');
} else {
// Migrate data to blue database
await migrateDatabase('green-db', 'blue-db');
}
}
async function migrateDatabase(source, target) {
// Implementation depends on your database
// Typically involves schema changes and data migration
}
Monitoring and Rollback
8. Health Check Endpoint
// health.js (Express endpoint)
router.get('/health', (req, res) => {
const health = {
status: 'OK',
version: process.env.APP_VERSION,
environment: process.env.ENVIRONMENT_NAME,
timestamp: new Date().toISOString(),
dependencies: {
database: checkDatabase(),
cache: checkCache()
}
};
res.status(200).json(health);
});
function checkDatabase() {
// Implementation specific to your database
return { status: 'OK', responseTime: 42 };
}
9. Automated Rollback Script
// rollback.js
async function rollback() {
try {
const metrics = await fetchMetrics();
if (metrics.errorRate > 0.1 || metrics.latency > 2000) {
console.log('Metrics threshold exceeded, initiating rollback');
await switchTraffic({
blueStack: greenConfig,
greenStack: blueConfig,
domain: 'app.example.com'
});
await notifyTeam('Rollback initiated due to performance degradation');
}
} catch (error) {
console.error('Rollback failed:', error);
await notifyTeam('Emergency rollback required!');
}
}
setInterval(rollback, 300000); // Check every 5 minutes
Best Practices Checklist
- Environment Setup
- [ ] Create identical blue and green environments
- [ ] Ensure database compatibility
- [ ] Configure monitoring for both environments
- Deployment Process
- [ ] Automate deployment to inactive environment
- [ ] Implement smoke tests
- [ ] Use weighted traffic shifting for canary testing
- Traffic Switching
- [ ] Plan for DNS TTL considerations
- [ ] Implement session affinity if needed
- [ ] Test switchover procedure
- Database Strategy
- [ ] Use backward-compatible database changes
- [ ] Implement data migration scripts
- [ ] Test rollback procedures
- Monitoring
- [ ] Set up health checks
- [ ] Monitor key metrics during switchover
- [ ] Implement automated rollback triggers
- Documentation
- [ ] Document switchover procedure
- [ ] Maintain runbooks for rollback
- [ ] Record previous deployments
- Testing
- [ ] Test in staging environment first
- [ ] Conduct failure scenario testing
- [ ] Validate rollback procedure