Products

HA Redis Cluster Migrations

Source

HA Redis migrations let multiple Eden Service nodes coordinate one live Redis Cluster migration while each node keeps its assigned traffic lanes local and fast. Use this mode when a Redis or Valkey migration has enough nodes, traffic, or availability risk that a single Eden worker should not own the whole run.

Mental Model

Each Redis source node maps to one migration lane. A lane records its source endpoint, target endpoint, role, traffic profile, active Eden owner, standby owners, checkpoint, replay watermark, and validation digest.

The hot request path stays lane-local. Eden does not consensus-order every Redis command. HA coordination only controls lane ownership, stage movement, validation barriers, and cutover decisions.

Deployment Shape

Run HA Redis migrations on the production HA profile:

  • 3, 5, or 7 Eden Service pods;
  • external Postgres;
  • external ClickHouse for analytics;
  • active-active HA enabled;
  • persistent Eden state per pod;
  • Blossom/cache-sync identity Secrets provisioned before startup; and
  • one immutable Eden image digest across the fleet.

The current release evidence covers the 3/5/7 shape. The internal checkpoint schema is larger, but operators should not run more than 7 migration participants until the chart, tests, and participant replacement workflow explicitly support that shape.

Eden podsUse whenControl-plane node loss toleratedMigration stage rule
3small HA migration or validation environment0all 3 confirm the same state
5ordinary production HA migration1all 5 confirm the same state
7larger production migration with more failure-domain headroom2all 7 confirm the same state

The migration stage rule is intentionally conservative: every configured Eden participant must confirm the same stage and state digest before Eden moves to the next forward stage.

Shared Postgres Authority

The shared Postgres deployment stores Eden domain tables, DBOS workflow tables, and the HA migration plan checkpoint. That does not make DBOS the HA stage authority.

When an HA migration plan exists:

  • the HA plan owns lane ownership, lease epochs, checkpoints, validation

digests, stage barriers, and cutover commitment;

  • DBOS owns durable workflow retries, sleeps, and restart recovery;
  • DBOS may drive the workflow and call the HA APIs;
  • DBOS must not mark the migration successful until the HA plan reaches

cutover_committed.

This gives operators one shared database without creating two competing stage machines.

Stage Flow

Forward stages are ordered:

text
created
  -> historical_copy
  -> live_capture
  -> dual_write
  -> catchup
  -> validate
  -> cutover_ready
  -> cutover_committed

Eden blocks stage movement until all required lane barriers and all participant confirmations pass.

Next stageRequired lane evidence
live_captureevery lane completed historical copy
dual_writeevery lane live-capture path is healthy
catchupevery primary lane dual-write path is healthy
validateevery lane target caught up to the replay watermark
cutover_readyevery lane caught up and source/target digests match
cutover_committedthe same caught-up and digest-matched evidence still holds

Rollback is available before cutover commit. After cutover commit, reversal is a separate compensating operation.

API Sequence

All paths are relative to /api/v1/migrations/{migration_id}.

StepAPIPurpose
Read planGET /ha/planCheck whether an HA plan exists and read the current revision and digest.
Install planPUT /ha/planInstall the lane set, participant set, deployment UUID, and initial stage.
Claim lanePOST /ha/lanes/{lane_id}/leaseClaim or renew one lane owner lease.
Checkpoint lanePATCH /ha/lanes/{lane_id}/checkpointPublish progress, replay watermarks, and validation digests under the active owner epoch.
Confirm statePOST /ha/confirmRecord one participant's confirmation of the current stage and state digest.
Advance stagePOST /ha/stageMove to the next stage after all barriers pass.

Example lane plan request:

json
{
  "expected_revision": 0,
  "deployment_uuid": "22222222-2222-4222-8222-222222222222",
  "participant_eden_uuids": [
    "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
    "bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb",
    "cccccccc-cccc-4ccc-8ccc-cccccccccccc"
  ],
  "lanes": [
    {
      "lane_id": "redis:primary:000",
      "source_endpoint_uuid": "11111111-1111-4111-8111-111111111111",
      "target_endpoint_uuid": "33333333-3333-4333-8333-333333333333",
      "role": "primary",
      "traffic_profile": {
        "read_percent": 90,
        "write_percent": 10,
        "average_ops_per_sec": 40000,
        "peak_ops_per_sec": 80000
      },
      "standby_eden_uuids": [
        "bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb",
        "cccccccc-cccc-4ccc-8ccc-cccccccccccc"
      ]
    }
  ]
}

For a Redis Cluster with 36 primaries and 36 replicas, create 72 lanes. Use the observed production traffic profile for each lane; a common starting point is 90/10 for primaries and 100/0 for read replicas.

Failure Behavior

If one Eden node fails, client sessions connected to that node fail and must reconnect. Other Eden nodes keep serving their lanes. When a failed node's lane leases expire, configured standby owners can claim those lanes and resume from durable checkpoints. Stale owners cannot publish progress after takeover because checkpoint writes require the active owner UUID and lease epoch.

Stage movement waits for every configured participant to confirm the same state. This is what prevents one node from cutting over while another node is behind or seeing different lane evidence.

Operator Caveat

The current production chart can derive the Eden node UUID from the Kubernetes pod UID. That means a replaced pod can receive a new node UUID. Installed HA migration plans currently treat the participant set as fixed for the run.

For long-running production migrations, use stable migration participant identities or wait for the participant replacement workflow before claiming operator-proof replacement of a participant mid-run.

Help improve Eden Docs

Find something unclear or incomplete? Review the source and propose an update.

View on GitLab Updated September 8, 2026