Understanding the Azure Redis Migration
Microsoft recently announced the retirement of Basic, Standard, and Premium tiers of Azure Cache for Redis, with a hard deadline of September 30, 2028. This affects many production workloads, and planning your migration strategy now will save headaches later.
Key Dates to Remember
- October 1, 2026: No new instances of Azure Cache for Redis can be created
- September 30, 2028: Migration deadline
- October 1, 2028: All remaining instances will be disabled
Pre-Migration Assessment
Inventory Your Redis Instances
# List all Redis caches across subscriptions
az redis list --query "[].{name:name, tier:sku.name, capacity:sku.capacity, location:location}" --output table
# Get detailed configuration for specific instance
az redis show --name <redis-name> --resource-group <rg-name>
Analyze Current Usage Patterns
# Export Redis metrics for capacity planning
az monitor metrics list \
--resource <redis-resource-id> \
--metric-names "connectedclients" "usedmemory" "serverLoad" "operationsPerSecond" \
--start-time 2024-01-01T00:00:00Z \
--end-time 2024-01-31T23:59:59Z \
--interval PT1H \
--output json > redis-metrics.json
Migration Strategy
1. Create Azure Managed Redis Instance
# Create new Managed Redis instance
az redis enterprise create \
--name <managed-redis-name> \
--resource-group <rg-name> \
--location <location> \
--sku Enterprise_E10 \
--capacity 2
# Create database within the instance
az redis enterprise database create \
--cluster-name <managed-redis-name> \
--resource-group <rg-name> \
--client-protocol Encrypted \
--clustering-policy EnterpriseCluster \
--eviction-policy NoEviction \
--modules name=RedisJSON,name=RedisTimeSeries
2. Data Migration Approaches
Option A: Redis MIGRATE Command (Small Datasets)
import redis
import time
# Connect to source and target
source = redis.Redis(
host='source-redis.redis.cache.windows.net',
port=6379,
password='source_password',
ssl=True
)
target = redis.Redis(
host='target-redis.region.redisenterprise.cache.azure.net',
port=10000,
password='target_password',
ssl=True
)
# Migrate keys
for key in source.scan_iter(count=100):
ttl = source.ttl(key)
value = source.dump(key)
if value:
target.restore(key, ttl if ttl > 0 else 0, value)
# Rate limiting to avoid overwhelming the system
time.sleep(0.001)
Option B: Redis Replication (Large Datasets)
# Export data from source
redis-cli -h source-redis.redis.cache.windows.net \
-p 6379 \
-a <password> \
--rdb dump.rdb \
--scan
# Import to target using redis-cli
redis-cli -h target-redis.region.redisenterprise.cache.azure.net \
-p 10000 \
-a <password> \
--pipe < dump.rdb
3. Application Configuration Updates
# Update your application configuration
# Old configuration
redis:
host: old-redis.redis.cache.windows.net
port: 6379
ssl: true
password: ${REDIS_PASSWORD}
# New configuration
redis:
host: new-redis.region.redisenterprise.cache.azure.net
port: 10000
ssl: true
password: ${MANAGED_REDIS_PASSWORD}
# Additional Managed Redis specific settings
cluster_enabled: true
read_replicas:
- host: replica1.region.redisenterprise.cache.azure.net
- host: replica2.region.redisenterprise.cache.azure.net
Testing and Validation
Performance Testing Script
import redis
import time
import statistics
def benchmark_redis_instance(connection_params, test_name):
r = redis.Redis(**connection_params)
# Test SET operations
set_times = []
for i in range(1000):
start = time.time()
r.set(f'test_key_{i}', 'x' * 1024) # 1KB payload
set_times.append(time.time() - start)
# Test GET operations
get_times = []
for i in range(1000):
start = time.time()
r.get(f'test_key_{i}')
get_times.append(time.time() - start)
print(f"\
{test_name} Results:")
print(f"SET - Avg: {statistics.mean(set_times)*1000:.2f}ms, "
f"P99: {sorted(set_times)[int(len(set_times)*0.99)]*1000:.2f}ms")
print(f"GET - Avg: {statistics.mean(get_times)*1000:.2f}ms, "
f"P99: {sorted(get_times)[int(len(get_times)*0.99)]*1000:.2f}ms")
# Benchmark both instances
benchmark_redis_instance(old_redis_config, "Azure Cache for Redis")
benchmark_redis_instance(new_redis_config, "Azure Managed Redis")
Cutover Strategy
Blue-Green Deployment Approach
# Step 1: Deploy application with dual-write capability
# Application writes to both old and new Redis
# Step 2: Verify data consistency
redis-cli -h old-redis.redis.cache.windows.net --scan --pattern '*' | wc -l
redis-cli -h new-redis.redisenterprise.cache.azure.net --scan --pattern '*' | wc -l
# Step 3: Switch reads to new Redis (canary deployment)
# Monitor error rates and latencies
# Step 4: Complete cutover
# Update DNS/load balancer to point to new Redis
Post-Migration Monitoring
# Set up alerts for the new Managed Redis instance
az monitor metrics alert create \
--name high-memory-usage \
--resource <managed-redis-id> \
--condition "avg usedmemorypercentage > 80" \
--window-size 5m \
--evaluation-frequency 1m
az monitor metrics alert create \
--name high-cpu-usage \
--resource <managed-redis-id> \
--condition "avg cpuusagepercentage > 75" \
--window-size 5m \
--evaluation-frequency 1m
Rollback Plan
Always maintain your rollback capability:
# Maintain bi-directional sync during transition
class DualRedisClient:
def __init__(self, primary_config, secondary_config):
self.primary = redis.Redis(**primary_config)
self.secondary = redis.Redis(**secondary_config)
def set(self, key, value, **kwargs):
# Write to both, read from primary
result = self.primary.set(key, value, **kwargs)
try:
self.secondary.set(key, value, **kwargs)
except Exception as e:
# Log but don't fail
logger.warning(f"Secondary write failed: {e}")
return result
def get(self, key):
return self.primary.get(key)
Key Takeaways
- Start Early: Don’t wait until 2027 to begin migration planning
- Test Thoroughly: Azure Managed Redis has different performance characteristics
- Plan for Downtime: While minimal downtime is possible, plan maintenance windows
- Monitor Costs: Managed Redis pricing model differs from Cache for Redis
- Update Documentation: Ensure runbooks and disaster recovery procedures are updated
The migration from Azure Cache for Redis to Azure Managed Redis is mandatory but also an opportunity to leverage improved performance, better scalability, and access to the latest Redis features. Plan your migration strategy now to ensure a smooth transition well before the 2028 deadline."