Phase 2: Astra DB to Apache Cassandra Data Migration (ZDM Proxy and CDM)
This phase moves the data. It assumes completion of ZDM Proxy and Data-Copy Setup: the proxy and bulk-copy tooling are configured to connect to Astra as the origin. It begins with standing up the target Apache Cassandra cluster, then moves traffic and data across.
The migration runs with no downtime. The proxy keeps the application serving traffic throughout, dual-writing to both databases while existing data is copied across in the background. For a typical dataset the copy runs over a few days depending on data volume, network bandwidth, and compaction load on the target.
Provision the target cluster
Section titled “Provision the target cluster”Stand up a new open-source Apache Cassandra cluster sized for the workload, choosing
the topology (node count, datacenters, replication factors) appropriate for the
intended deployment. Install the monitoring agent on each node and confirm every node
reports UN (Up/Normal) in nodetool status. Then recreate the schema, roles, and
credentials captured during assessment before the proxy starts
dual-writing, as set out in the
target preparation prerequisite.
When migrating from a managed service, the operator takes on cluster management
responsibilities. The install should be automated rather than built node by node;
automation makes the cluster repeatable and consistent, removes a whole class of human
error, and makes scaling, rebuilding, or standing up matching test and production
environments a routine operation. AxonOps publishes ready-to-use configuration
management for this purpose: the
AxonOps Ansible collection
and the AxonOps Chef cookbook install and
configure Apache Cassandra together with the axon-agent that connects to AxonOps
Cloud or to a self-hosted axon-server. For other approaches, such as baking golden
machine images, AxonOps can assist in selecting one suited to the organisation's
tooling. See
why Ansible is recommended for Cassandra
in the installation guide to get started.
Astra handled time synchronization automatically. On a self-managed cluster, clock
synchronization is the operator's responsibility and has material consequences. In all
Cassandra versions, conflicting writes are resolved by timestamp (last write wins) and
TTL expiry is timestamp-driven,
so the nodes in a cluster must have closely synchronised clocks. If clocks drift,
writes may appear lost, deleted data may reappear, and reads may differ depending on
which replica answers. Configure a reliable time service (for example, chrony) on
every node before the cluster takes traffic, and point all nodes at the same time
source: the cloud provider's NTP service (such as time.aws.com or time.google.com)
in the cloud, or a dedicated set of NTP servers on-premises. Monitor clock offset on
an ongoing basis; AxonOps surfaces per-node NTP offset, confirming that cluster clocks
are synchronized and alerting when a node starts to drift. See
AxonOps for Cassandra.
- Deploy the ZDM Proxy between the application and both databases, and repoint the application at the proxy. Reads go to Astra; writes are dual-written to both Astra and the target. From this moment, all new data is kept in sync on both sides.
- Review the copy-tool caveats for collections, user-defined types (UDTs), and TTLs before starting the bulk copy. See Operational Caveats.
- Run the bulk copy to move the data that already existed in Astra before dual-writes began. With CDM, copy user-table data from the origin to the target and let it validate row-level consistency. Redirect its output to a log file so any issues can be investigated. For assistance running CDM, contact AxonOps.
- Review the copy logs. Confirm the error set is acceptable. If not, re-run the copy, because subsequent passes reduce the error count.
- Enable asynchronous dual reads in the proxy configuration so that reads are served against both databases and the target's read path is exercised under real load ahead of cutover.
CDM is the recommended tool for this migration, because it copies and validates
row-level consistency out of the box. Other tools can perform the bulk copy with the
same ZDM Proxy dual-write setup; only the bulk-backfill tool changes. DataStax Bulk
Loader (DSBulk) unloads a table from Astra to files and loads them into the target,
connecting to Astra with the Secure Connect Bundle (-b) and the token username and
to the target with host, port, and credentials; validate with dsbulk count (see
Validation). Apache Spark, using the open-source
spark-cassandra-connector, reads from Astra via the Secure Connect Bundle and writes
to the target; this suits teams who already run Spark or have existing ETL pipelines.
With DSBulk or Spark, the operator builds and validates the copy logic separately,
whereas CDM provides both out of the box.
Preserve write timestamps and TTLs during the bulk copy
Problem: The bulk copy must carry the original write timestamps and TTLs on every row. Without them, every migrated row appears to have been written at migration time.
Symptoms: TTL-based expiry is broken (data lives too long or expires at the wrong time), and last-write-wins conflict resolution is corrupted against concurrent dual-writes.
Instead: CDM preserves write timestamps and TTLs by default. Tools that do not, such as DataStax Bulk Loader (DSBulk) or Apache Spark, must be configured to carry the original timestamp and TTL on every row.
Size the bulk-copy host and the target cluster for the data volume: an undersized copy host runs out of memory or drags on for days, and an undersized target cannot absorb the write load. Tune the target to be write-tolerant during the bulk phase, then re-tune for the normal read/write mix once the copy is done. When using a file-based tool such as DSBulk, delete the intermediate dump files after each table loads successfully so a large migration does not fill the disk. Script and version-control the copy commands, proxy deployment, and validation so the process is repeatable across test and production runs.
If the data has short TTLs (days or weeks), the bulk copy may be skippable. Deploy the ZDM Proxy with dual-writes enabled and leave it running until all pre-existing data in Astra has expired naturally. Once the TTL window has passed, the target holds a complete dataset from dual-writes alone. This trades migration time for simplicity.
Counter tables need special handling
Section titled “Counter tables need special handling”Counter tables do not fit the standard dual-write and bulk-copy flow, and getting them wrong produces silently incorrect totals. Plan for them separately.
The problem is that counter updates are increments, not absolute values, and they are not idempotent. During the migration the proxy dual-writes each new increment to both Astra and the target, while the bulk copy carries the existing counter total from Astra to the target. Any increment that lands during the copy window is then applied to the target twice (once in the copied total and once through the dual-write), or missed entirely, depending on ordering. Either way the target ends up with the wrong value. For this reason CDM does not copy counter tables when missing by default.
The safe approach is to take counter tables out of the main flow and migrate them in a dedicated step:
- Exclude counter tables from the bulk copy used for the rest of the data.
- Migrate each counter table once, with no concurrent increments to double-count. In practice this means copying the authoritative counter values during a short window in which updates to those specific tables are paused or quiesced, so nothing is counted twice.
- Direct counter traffic to the target as part of cutover, so increments resume against the migrated values.
The right sequencing depends on how the application uses counters, for example whether increments can be paused briefly, and whether the values are recomputable from source data. If counters are central to the workload, talk to AxonOps so the approach can be designed and tested for the specific case before migration.
Go / No-Go
Section titled “Go / No-Go”Go: no dropped read or write requests on either side, and the bulk copy has completed with an acceptable, understood error set.
Rollback: reconfigure the ZDM Proxy to route all traffic back to Astra, and remove the target cluster. Because reads have not yet been switched to the target, this is a clean rollback.
Cluster-level monitoring does not see what happens inside the proxy layer. The AxonOps ZDM Proxy fork exposes migration metrics (origin reads, dual reads, and target reads) that surface degradations or failures visible only at the proxy; run these alongside monitoring on the target cluster. See AxonOps for Cassandra.
Once the data is copied and dual reads are running cleanly, move on to Validation.