Eden enables zero-downtime database migrations by proxying application traffic and handling data replication
transparently. This document describes the production architecture using DNS-based traffic routing.
Eden sits between your applications and databases. By pointing your applications to Eden via DNS, Eden can:
Applications never know a migration happened.
┌─────────────────────────────────────────────────────────────────────────────┐
│ Customer VPC │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ App 1 │ │ App 2 │ │ App N │ │
│ │ │ │ │ │ │ │
│ │ REDIS_HOST= │ │ REDIS_HOST= │ │ REDIS_HOST= │ │
│ │ redis.int │ │ redis.int │ │ redis.int │ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │ │
│ └────────────────┼────────────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────┐ │
│ │ DNS Resolution │ │
│ │ redis.internal │ │
│ └─────────┬─────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────┐ │
│ │ │ │
│ │ Eden Proxy │ │
│ │ │ │
│ └─────────┬─────────┘ │
│ │ │
│ ┌────────────┴────────────┐ │
│ │ │ │
│ ▼ ▼ │
│ ┌───────────────────┐ ┌───────────────────┐ │
│ │ Source Database │ │ Target Database │ │
│ │ (current) │ │ (migration dest) │ │
│ └───────────────────┘ └───────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘Customer updates their DNS or application config to point to Eden.
Before:
redis.internal → 10.0.1.50 (Source Redis)After:
redis.internal → 10.0.2.100 (Eden Proxy)At this point:
┌─────┐ ┌──────┐ ┌────────────┐
│ App │ ───▶ │ Eden │ ───▶ │ Source DB │
└─────┘ └──────┘ └────────────┘Eden begins replicating data from Source to Target.
┌─────┐ ┌──────┐ ┌────────────┐
│ App │ ───▶ │ Eden │ ───▶ │ Source DB │
└─────┘ └──────┘ └────────────┘
│
│ replication
▼
┌────────────┐
│ Target DB │
└────────────┘Before cutover, Eden validates:
# Eden API
curl https://eden-api/migrations/abc123/status
{
"phase": "validating",
"replication_lag_ms": 0,
"source": "healthy",
"target": "healthy",
"ready_for_cutover": true
}Eden switches the upstream from Source to Target.
┌─────┐ ┌──────┐ ┌────────────┐
│ App │ ───▶ │ Eden │ ─ ✗ │ Source DB │ (disconnected)
└─────┘ └──────┘ └────────────┘
│
│ now primary
▼
┌────────────┐
│ Target DB │
└────────────┘After validation on Target:
Eden deployed as a VM or container in customer's VPC.
Customer VPC
┌─────────────────────────────────────────────────────┐
│ │
│ ┌──────┐ ┌──────┐ ┌──────────────┐ │
│ │ Apps │ ───▶ │ Eden │ ───▶ │ Redis │ │
│ └──────┘ └──────┘ └──────────────┘ │
│ │
└─────────────────────────────────────────────────────┘Benefits: Low latency, traffic stays in VPC
Eden runs alongside each application (same VM or Kubernetes pod).
┌─────────────────────────────┐
│ App VM / Pod │
│ ┌─────┐ ┌─────┐ │
│ │ App │ ───▶ │Eden │ ─────-┼───▶ Redis
│ └─────┘ └─────┘ │
│ localhost │
└─────────────────────────────┘Benefits: No DNS change needed (localhost), lowest latency
Create a DNS record in your private hosted zone:
# AWS Route53 example
aws route53 change-resource-record-sets \
--hosted-zone-id Z123456 \
--change-batch '{
"Changes": [{
"Action": "UPSERT",
"ResourceRecordSet": {
"Name": "redis.internal",
"Type": "A",
"TTL": 30,
"ResourceRecords": [{"Value": "10.0.2.100"}]
}
}]
}'redis.internal CNAME eden-proxy.internalNo DNS change — update app config directly:
# Before
REDIS_HOST: myredis.redis.cache.azure.com
# After
REDIS_HOST: eden-proxy.internalAt any point, rollback is a DNS change away:
redis.internal → Source Redis IPApps reconnect to Source directly. Eden removed from path.
redis.internal → Source Redis IPReplication stops. Source still has all data. No data loss.
# Option A: DNS rollback to Source (if Source still has data)
redis.internal → Source Redis IP
# Option B: Eden rollback (switch upstream back to Source)
curl -X POST https://eden-api/migrations/abc123/rollback[//]: # (## High Availability)
[//]: # ()
[//]: # (For production, run multiple Eden instances behind a load balancer:)
[//]: # ()
[//]: # (```)
[//]: # ( ┌─────────────────┐)
[//]: # ( │ Load Balancer │)
[//]: # ( │ redis.internal │)
[//]: # ( └────────┬────────┘)
[//]: # ( │)
[//]: # ( ┌─────────────┼──────────────┐)
[//]: # ( ▼ ▼ ▼)
[//]: # ( ┌────────┐ ┌────────┐ ┌────────┐)
[//]: # ( │ Eden 1 │ │ Eden 2 │ │ Eden 3 │)
[//]: # ( └────┬───┘ └───┬-───┘ └────┬───┘)
[//]: # ( │ │ │)
[//]: # ( └─────────────┴──────────-───┘)
[//]: # ( │)
[//]: # ( ▼)
[//]: # ( ┌──────────────┐)
[//]: # ( │ Redis │)
[//]: # ( └──────────────┘)
[//]: # (```)
[//]: # ()
[//]: # (Eden instances share state via:)
[//]: # ()
[//]: # (- Shared PostgreSQL for migration metadata)
[//]: # (- Coordination for cutover (leader election))
[//]: # ()
[//]: # (---)
Eden can terminate TLS from apps and establish new TLS to databases:
App ──TLS──▶ Eden ──TLS──▶ RedisEden passes through AUTH commands transparently. No credential storage needed.
Eden should be deployed in a private subnet with:
Key metrics to monitor:
| Metric | Description | Alert Threshold |
|---|---|---|
eden_proxy_latency_ms | Added latency from proxy | > 1ms |
eden_replication_lag_ms | How far behind Target is | > 1000ms |
eden_connections_active | Current client connections | Baseline |
eden_throughput_ops | Operations per second | Baseline |
eden_errors_total | Connection/protocol errors | > 0 |
10.0.1.50:6379REDIS_HOST=redis.internalredis.internal → 10.0.1.50# Deploy Eden VM at 10.0.2.100
eden-server --listen 0.0.0.0:6379
# Create source endpoint
curl http://10.0.2.100:8000/api/v1/endpoints \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-d '{
"id": "ec2_redis",
"uri": "redis://10.0.1.50:6379"
}'
# Create target endpoint
curl http://10.0.2.100:8000/api/v1/endpoints \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-d '{
"id": "azure_redis",
"uri": "redis://myredis.redis.cache.azure.com:6380"
}'# Update DNS
redis.internal → 10.0.2.100Validate:
redis-cli -h redis.internal PING
# Returns: PONG (via Eden)curl http://10.0.2.100:8000/api/v1/migrations \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-d '{
"id": "ec2_to_azure",
"description": "Migrate from EC2 Redis to Azure Cache",
"strategy": {
"type": "canary",
"read_percentage": 0.05,
"write_mode": {
"mode": "dual_write",
"policy": "old_authoritative"
}
},
"data": {
"type": "scan",
"replace": "replace"
},
"failure_handling": "rollback_all"
}'
# Add API/Interlay to migration
curl http://10.0.2.100:8000/api/v1/migrations/ec2_to_azure/interlay/redis_interlay \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-d '{
"endpoint": "azure_redis"
}'# Start migration
curl http://10.0.2.100:8000/api/v1/migrations/ec2_to_azure/migrate \
-H "Authorization: Bearer $TOKEN" \
-X POST
# Monitor status
curl http://10.0.2.100:8000/api/v1/migrations/ec2_to_azure \
-H "Authorization: Bearer $TOKEN"# Increase to 25% read traffic
curl http://10.0.2.100:8000/api/v1/migrations/ec2_to_azure \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-X PATCH \
-d '{
"strategy": {
"type": "canary",
"read_percentage": 0.25,
"write_mode": {"mode": "dual_write", "policy": "old_authoritative"}
}
}'
# Increase to 75%
curl http://10.0.2.100:8000/api/v1/migrations/ec2_to_azure \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-X PATCH \
-d '{
"strategy": {
"type": "canary",
"read_percentage": 0.75,
"write_mode": {"mode": "dual_write", "policy": "old_authoritative"}
}
}'# Full cutover to Azure
curl http://10.0.2.100:8000/api/v1/migrations/ec2_to_azure \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-X PATCH \
-d '{
"strategy": {
"type": "canary",
"read_percentage": 1.0,
"write_mode": {"mode": "cutover", "write_percentage": 1.0}
}
}'
# Verify completion
curl http://10.0.2.100:8000/api/v1/migrations/ec2_to_azure \
-H "Authorization: Bearer $TOKEN"# Remove Eden from path after validation
redis.internal → myredis.redis.cache.azure.comQ: What latency does Eden add?
A: Typically < 1ms for in-VPC deployments. Eden is a pass-through proxy with minimal processing.
Q: What if Eden crashes during migration?
A: Apps reconnect automatically. If during replication, resume from last checkpoint. If during cutover, Eden coordinates
to ensure atomicity.
Q: Can I migrate between different database types?
A: Eden supports protocol-compatible migrations (Redis → Redis, PostgreSQL → PostgreSQL). Cross-database migrations
require application changes.
Q: Do apps need to be restarted?
A: No. DNS TTL expiry + connection pool refresh handles it. For long-lived connections, a rolling restart may speed up
the transition.
Q: What about connection limits?
A: Eden multiplexes connections. 1000 app connections may only need 10 connections to the database.