<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Adiom</title><description>Fast, secure data migration and replication solutions for NoSQL databases</description><link>https://www.adiom.io/</link><language>en-us</language><item><title>One Database Is a Liability: Splitting Tenant Data Across Clusters Without Losing Your Mind</title><link>https://www.adiom.io/post/one-database-is-a-liability-splitting-tenant-data-across-clusters-without-losing-your-mind/</link><guid isPermaLink="true">https://www.adiom.io/post/one-database-is-a-liability-splitting-tenant-data-across-clusters-without-losing-your-mind/</guid><description>A single shared database is the easiest way to start a multi-tenant product - and one of the fastest ways to back yourself into a corner.</description><pubDate>Tue, 09 Jun 2026 22:40:06 GMT</pubDate><content:encoded>&lt;p&gt;A single shared database is the easiest way to start a multi-tenant product - and one of the fastest ways to back yourself into a corner. As you scale, four forces pull your data apart: compliance, locality, quality of service, and blast radius. This is how to architect for that split, and how to move tenants between clusters when - not if - you have to.&lt;/p&gt;
&lt;h2 id=&quot;why-one-cluster-stops-working&quot;&gt;Why One Cluster Stops Working&lt;/h2&gt;
&lt;p&gt;In the beginning, every tenant lives happily in one database. It’s simple, it’s cheap, and it’s exactly the right call. But growth has a way of turning that simplicity into a constraint. Sooner or later, four distinct pressures show up - usually all at once - and none of them are solved by buying a bigger box.&lt;/p&gt;
&lt;table class=&quot;_4FIAL&quot; data-hook=&quot;table-component&quot; style=&quot;border-spacing:0;border-collapse:separate&quot;&gt;&lt;colgroup&gt;&lt;col style=&quot;width:120px;min-width:120px&quot;&gt;&lt;col style=&quot;width:338.125px;min-width:120px&quot;&gt;&lt;/colgroup&gt;&lt;tbody&gt;&lt;tr style=&quot;height:47px&quot;&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;a6uot2916&quot; data-visual-col=&quot;0&quot; data-visual-row=&quot;0&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-7kbea2969&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;strong style=&quot;font-weight:700&quot;&gt;&lt;span&gt;Compliance&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;a2ek92918&quot; data-visual-col=&quot;1&quot; data-visual-row=&quot;0&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:-0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;right:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-q1yp83008&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;A healthcare customer needs their data isolated under HIPAA. An EU customer&apos;s records can&apos;t leave the EU under GDPR. A government tenant needs a sovereign environment entirely. &quot;Just add a &lt;/span&gt;&lt;em style=&quot;font-style:italic&quot;&gt;&lt;span&gt;tenant_id&lt;/span&gt;&lt;/em&gt;&lt;span&gt; column&quot; doesn&apos;t satisfy an auditor who wants hard isolation boundaries.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height:47px&quot;&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;cu9r12921&quot; data-visual-col=&quot;0&quot; data-visual-row=&quot;1&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-hfond2975&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;strong style=&quot;font-weight:700&quot;&gt;&lt;span&gt;Locality&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;9f9go2923&quot; data-visual-col=&quot;1&quot; data-visual-row=&quot;1&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:-0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;right:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-72gvx3059&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Your tenant in Sydney shouldn&apos;t pay a 200ms round-trip to a database in Virginia. Latency is a product feature, and the only way to fix it is to put data physically close to the users who read and write it.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height:47px&quot;&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;exj822926&quot; data-visual-col=&quot;0&quot; data-visual-row=&quot;2&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-i0dbs2994&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;strong style=&quot;font-weight:700&quot;&gt;&lt;span&gt;Quality of Service (QoS)&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;ngdqg2928&quot; data-visual-col=&quot;1&quot; data-visual-row=&quot;2&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:-0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;right:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-p2yk83141&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;One enterprise tenant runs a runaway analytical query and suddenly everyone shares the pain. Noisy neighbors are inevitable in a shared cluster. Dedicated or pooled clusters let you guarantee performance tiers and stop one tenant from degrading the rest.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height:47px&quot;&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;bb0n12931&quot; data-visual-col=&quot;0&quot; data-visual-row=&quot;3&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;bottom:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-jdzwd3002&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;strong style=&quot;font-weight:700&quot;&gt;&lt;span&gt;Blast Radius&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;r5bf62933&quot; data-visual-col=&quot;1&quot; data-visual-row=&quot;3&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:-0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;bottom:-0.5px;left:-0.5px;right:-0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;right:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-iis4c3156&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;A bad migration, a corrupt index, a failover gone wrong - in a single cluster, that&apos;s an incident for every customer at once. Partitioning tenants across clusters means a failure is contained to a slice of your business, not all of it.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;The goal isn’t more databases for their own sake. It’s the ability to draw isolation boundaries on purpose, where the business actually needs them.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;the-architecture-five-components-that-make-it-work&quot;&gt;The Architecture: Five Components That Make It Work&lt;/h2&gt;
&lt;p&gt;A regional, multi-cluster, multi-tenant system isn’t one big piece of software - it’s a handful of components that each do one job well. Get these five right and the rest is detail.&lt;/p&gt;
&lt;p&gt;The five components of a regional multi-tenant data platform&lt;/p&gt;
&lt;h3 id=&quot;1-application-level-routing&quot;&gt;1. Application-level routing&lt;/h3&gt;
&lt;p&gt;The router is the brain. Every request carries a tenant identity, and the application layer maps that identity to the right cluster - tenant → cluster - before any query is issued. This map is the source of truth for where a tenant’s data lives. It needs to be fast, cached close to the application, and - critically - updatable at runtime, because the day you move a tenant, the router is what makes the cutover real. Routing at the application layer, often as a service side car (rather than relying on a database-side proxy), keeps the logic explicit, testable, and tied to your domain’s notion of a tenant.&lt;/p&gt;
&lt;h3 id=&quot;2-database-clusters&quot;&gt;2. Database clusters&lt;/h3&gt;
&lt;p&gt;These are the homes for your data: a fleet of clusters partitioned by region, compliance regime, or service tier. Some are pooled (many small tenants sharing a cluster for cost efficiency), some are dedicated (one large or sensitive tenant per cluster). The architecture has to treat clusters as interchangeable destinations - provisionable, decommissionable, and addressable by the router - rather than hand-tuned pets.&lt;/p&gt;
&lt;h3 id=&quot;3-data-mover&quot;&gt;3. Data mover&lt;/h3&gt;
&lt;p&gt;This is the component most teams underestimate, and it’s the reason this post exists. Tenants don’t stay put. They outgrow their pooled cluster, change compliance requirements, or need to move to a new region. The data mover is what relocates a tenant’s data from one cluster to another - ideally live, with the tenant’s application still serving traffic the whole time. Without it, every one of the four pressures above eventually becomes a wall you can’t get past.&lt;/p&gt;
&lt;h3 id=&quot;4-observability&quot;&gt;4. Observability&lt;/h3&gt;
&lt;p&gt;With data spread across many clusters, “is the system healthy?” becomes a per-cluster, per-tenant question. You need unified visibility into cluster load, per-tenant resource consumption, replication lag, and the progress and integrity of any in-flight migration. Observability is also what tells you when to move a tenant - it’s the signal that a cluster is getting hot or a neighbor is getting noisy.&lt;/p&gt;
&lt;h3 id=&quot;5-control-panel&quot;&gt;5. Control panel&lt;/h3&gt;
&lt;p&gt;The control panel is the operator’s cockpit: provision a cluster, place a tenant, kick off a migration, watch it land, update the routing map, and decommission what’s empty. It turns a set of powerful-but-dangerous primitives into repeatable, auditable operations. The better the control panel, the less every tenant move depends on one engineer remembering the runbook.&lt;/p&gt;
&lt;h2 id=&quot;but-mongodb-already-has-sharding---why-thats-not-the-same-thing&quot;&gt;“But MongoDB Already Has Sharding” - Why That’s Not the Same Thing&lt;/h2&gt;
&lt;p&gt;If you’re on MongoDB, the database can shard for you. Why run twelve independent replica sets behind an application-level router when you could run one &lt;strong&gt;12-shard cluster&lt;/strong&gt; and let the balancer spread tenants across shards automatically (using sharding tags)? Both spread data across twelve sets of hardware. They are not the same architecture.&lt;/p&gt;
&lt;p&gt;A single sharded cluster is &lt;em&gt;one&lt;/em&gt; logical database. That’s the whole point of it - and also the catch. A 12-shard cluster shares config servers, a balancer, a version, and a maintenance window across all twelve shards. Twelve replica sets with app-level routing are twelve genuinely independent databases that happen to be coordinated by your application.&lt;/p&gt;
&lt;table class=&quot;_4FIAL&quot; data-hook=&quot;table-component&quot; style=&quot;border-spacing:0;border-collapse:separate&quot;&gt;&lt;colgroup&gt;&lt;col style=&quot;width:65px;min-width:65px&quot;&gt;&lt;col style=&quot;width:65px;min-width:65px&quot;&gt;&lt;col style=&quot;width:65px;min-width:65px&quot;&gt;&lt;/colgroup&gt;&lt;tbody&gt;&lt;tr style=&quot;height:47px&quot;&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;z4ryj8797&quot; data-visual-col=&quot;0&quot; data-visual-row=&quot;0&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;div class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-xugsd8798&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;br role=&quot;presentation&quot;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;fxja28799&quot; data-visual-col=&quot;1&quot; data-visual-row=&quot;0&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-j1iw18891&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;strong style=&quot;font-weight:700&quot;&gt;&lt;span style=&quot;color:#4BB3E5;text-decoration:inherit&quot;&gt;&lt;span&gt;12-shard cluster&lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;o3zt48801&quot; data-visual-col=&quot;2&quot; data-visual-row=&quot;0&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:-0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;right:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-4srpv8930&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;strong style=&quot;font-weight:700&quot;&gt;&lt;span style=&quot;color:#4BB3E5;text-decoration:inherit&quot;&gt;&lt;span&gt;12 replica sets + app routing&lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height:47px&quot;&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;zqi9o8804&quot; data-visual-col=&quot;0&quot; data-visual-row=&quot;1&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-6goav8970&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;strong style=&quot;font-weight:700&quot;&gt;&lt;span&gt;Blast radius&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;z5aii8806&quot; data-visual-col=&quot;1&quot; data-visual-row=&quot;1&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-70ksj9182&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Shared config servers and balancer - a control-plane problem can affect the whole cluster&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;vig5o8808&quot; data-visual-col=&quot;2&quot; data-visual-row=&quot;1&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:-0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;right:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-psj2g10236&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Each replica set fails on its own; one going down touches only its tenants&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height:47px&quot;&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;gk1zg8811&quot; data-visual-col=&quot;0&quot; data-visual-row=&quot;2&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-aawls9011&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;strong style=&quot;font-weight:700&quot;&gt;&lt;span&gt;Compliance / locality&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;it0gx8813&quot; data-visual-col=&quot;1&quot; data-visual-row=&quot;2&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-l9ufs10284&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;One cluster, typically one region and one trust boundary&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;32qrn8815&quot; data-visual-col=&quot;2&quot; data-visual-row=&quot;2&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:-0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;right:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-lgc3o10332&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Put each replica set in its own region or compliance regime, independently&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height:47px&quot;&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;2sye08818&quot; data-visual-col=&quot;0&quot; data-visual-row=&quot;3&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-xmkdy9054&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;strong style=&quot;font-weight:700&quot;&gt;&lt;span&gt;Upgrades &amp;amp; maintenance&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;1k7j38820&quot; data-visual-col=&quot;1&quot; data-visual-row=&quot;3&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-t2qxh10382&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Version and maintenance windows are cluster-wide&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;ee4oo8822&quot; data-visual-col=&quot;2&quot; data-visual-row=&quot;3&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:-0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;right:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-2l67a10432&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Upgrade or patch one tenant&apos;s database without touching the rest&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height:47px&quot;&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;ipmmj8825&quot; data-visual-col=&quot;0&quot; data-visual-row=&quot;4&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-tyhiy9097&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;strong style=&quot;font-weight:700&quot;&gt;&lt;span&gt;Tenant placement&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;c3dcr8827&quot; data-visual-col=&quot;1&quot; data-visual-row=&quot;4&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-dy58y10484&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;The balancer decides and moves, by shard key and tags - not by your business rules&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;u5kfb8829&quot; data-visual-col=&quot;2&quot; data-visual-row=&quot;4&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:-0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;right:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-h99b810986&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;You place tenants explicitly, by tier, region, or contract&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height:47px&quot;&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;02y908832&quot; data-visual-col=&quot;0&quot; data-visual-row=&quot;5&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;bottom:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-gvz519141&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;strong style=&quot;font-weight:700&quot;&gt;&lt;span&gt;Moving a tenant&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;z3ahd8834&quot; data-visual-col=&quot;1&quot; data-visual-row=&quot;5&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;bottom:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-o4bkh12264&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Chunk migration within one cluster; can&apos;t move a tenant to a different region or trust boundary&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;s36ea8836&quot; data-visual-col=&quot;2&quot; data-visual-row=&quot;5&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:-0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;bottom:-0.5px;left:-0.5px;right:-0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;right:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-ihf9l12330&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;A data-mover job relocates a tenant to any other cluster, anywhere&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Native sharding is excellent at what it’s for: scaling a single dataset horizontally when you don’t need isolation between the rows. But the four pressures in this post - compliance, locality, QoS, and blast radius - are all about drawing &lt;em&gt;boundaries&lt;/em&gt;, and a sharded cluster is deliberately built to erase them. App-level routing over independent clusters keeps you in control of where each boundary sits. The trade is that you now own the routing map and the tenant moves yourself - which is exactly why the data mover matters.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Sharding spreads one database wider. App-level routing across independent clusters gives you many databases you can place, isolate, and move on purpose.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;the-hard-part-migrating-big-tenants-live&quot;&gt;The Hard Part: Migrating Big Tenants, Live&lt;/h2&gt;
&lt;p&gt;Here’s the irony at the center of multi-tenant operations. You almost never need to move a tenant when they’re small and easy. You need to move them precisely when they’ve become &lt;strong&gt;big&lt;/strong&gt; - hundreds of gigabytes or more - and important, and busy. The migration you can’t avoid is also the one that’s hardest to pull off.&lt;/p&gt;
&lt;p&gt;And the constraints stack up fast. A tenant migration in a live multi-tenant system has to satisfy all of these at once:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Minimal interruption of service.&lt;/strong&gt; The tenant is in production. You don’t get to take them offline for a weekend.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Automated or semi-automated.&lt;/strong&gt; If every move requires an engineer babysitting a UI for eight hours, you’ll never do it often enough to keep up.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Filtered at the source.&lt;/strong&gt; You’re moving one tenant out of a shared cluster - not the whole database. The mover has to select just that tenant’s data, cleanly.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Into a non-empty destination.&lt;/strong&gt; The target cluster already hosts other tenants. You’re merging into a live dataset, not restoring into a blank slate.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Carefully throttled.&lt;/strong&gt; The source cluster is still serving every other tenant. A migration that saturates I/O turns one tenant’s move into everyone else’s outage - exactly the blast radius you were trying to avoid.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Now look at what most data migration tooling actually assumes:&lt;/p&gt;
&lt;table class=&quot;_4FIAL&quot; data-hook=&quot;table-component&quot; style=&quot;border-spacing:0;border-collapse:separate&quot;&gt;&lt;colgroup&gt;&lt;col style=&quot;width:65px;min-width:65px&quot;&gt;&lt;col style=&quot;width:65px;min-width:65px&quot;&gt;&lt;/colgroup&gt;&lt;tbody&gt;&lt;tr style=&quot;height:47px&quot;&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;51e7514450&quot; data-visual-col=&quot;0&quot; data-visual-row=&quot;0&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-tzicq14721&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;strong style=&quot;font-weight:700&quot;&gt;&lt;span style=&quot;color:#4BB3E5;text-decoration:inherit&quot;&gt;&lt;span&gt;Most migration tools expect…&lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;tl16c14452&quot; data-visual-col=&quot;1&quot; data-visual-row=&quot;0&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:-0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;right:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-at08b14797&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;strong style=&quot;font-weight:700&quot;&gt;&lt;span style=&quot;color:#4BB3E5;text-decoration:inherit&quot;&gt;&lt;span&gt;Multi-tenant reality&lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height:47px&quot;&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;yxv9l14455&quot; data-visual-col=&quot;0&quot; data-visual-row=&quot;1&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-o4vgw15219&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Dedicated infrastructure you provision and babysit&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;uh68q14457&quot; data-visual-col=&quot;1&quot; data-visual-row=&quot;1&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:-0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;right:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-jcqwf15449&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;You want it to run as a job on infra you already have&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height:74px&quot;&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;x7of114460&quot; data-visual-col=&quot;0&quot; data-visual-row=&quot;2&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-y6a6v15528&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;A one-shot bulk copy, no live changes without complicated setup&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;cmyya14462&quot; data-visual-col=&quot;1&quot; data-visual-row=&quot;2&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:-0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;right:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-9ugan15608&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;The tenant keeps writing throughout&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height:47px&quot;&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;9eerg14465&quot; data-visual-col=&quot;0&quot; data-visual-row=&quot;3&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-59p1h17743&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;An operator clicking through a UI&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;ot6yp14467&quot; data-visual-col=&quot;1&quot; data-visual-row=&quot;3&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:-0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;right:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-5olxq17905&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;You need it scripted and repeatable&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height:47px&quot;&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;spp8h14470&quot; data-visual-col=&quot;0&quot; data-visual-row=&quot;4&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-c397y17988&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;An empty destination&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;97ltc14472&quot; data-visual-col=&quot;1&quot; data-visual-row=&quot;4&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:-0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;right:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-7ihzx18072&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;The target already has tenants on it&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height:47px&quot;&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;2z13o14475&quot; data-visual-col=&quot;0&quot; data-visual-row=&quot;5&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-4896u18157&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Migrate the whole dataset&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;ase1814477&quot; data-visual-col=&quot;1&quot; data-visual-row=&quot;5&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:-0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;right:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-c6dhj18243&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;You need to filter to one or several tenants at the source&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height:47px&quot;&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;bq6mn14480&quot; data-visual-col=&quot;0&quot; data-visual-row=&quot;6&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;bottom:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-mso7a19350&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Run flat-out, as fast as possible&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;z2qt114482&quot; data-visual-col=&quot;1&quot; data-visual-row=&quot;6&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:-0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;bottom:-0.5px;left:-0.5px;right:-0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;right:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-2lh7619438&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;You must throttle to protect production neighbors&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;Standard migration tools are built for the empty-to-empty, take-it-offline, click-the-button case. Multi-tenant migrations are none of those things.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;how-we-solved-it-dsync-as-the-data-mover&quot;&gt;How We Solved It: Dsync as the Data Mover&lt;/h2&gt;
&lt;p&gt;For one of our customers running exactly this kind of regional multi-tenant platform, we used &lt;a href=&quot;https://github.com/adiom-data/dsync&quot;&gt;Dsync&lt;/a&gt; as the data mover - and it lines up against the constraints above point for point. Dsync was built for live production migrations, which is precisely what a tenant move demands:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Live migration.&lt;/strong&gt; Initial sync plus change data capture, so the tenant keeps serving traffic while their data moves. The cutover is a routing-map flip, not a downtime window.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;No specialized infrastructure.&lt;/strong&gt; Dsync runs as Kubernetes jobs on the cluster you already operate - nothing extra to provision, secure, and tear down for every move.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Source-side filtering.&lt;/strong&gt; Move exactly one tenant’s data out of a shared cluster, instead of the entire dataset.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Merges into non-empty destinations.&lt;/strong&gt; Land a tenant on a cluster that’s already serving other tenants - the realistic case, not the demo case.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Load-level throttling.&lt;/strong&gt; Cap the migration’s footprint so the source cluster keeps its performance promises to every other tenant on it.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Fast and resumable.&lt;/strong&gt; Parallelized copy for hundreds of gigabytes, and if something interrupts a run, it picks up where it left off instead of starting over.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Observable and secure, with embedded validation.&lt;/strong&gt; You can watch progress and lag in real time, and Dsync verifies data integrity as part of the move - so you cut over on evidence, not hope.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The result is a tenant migration that behaves like a routine operation instead of a heart-surgery event: filtered at the source, throttled for the neighbors, merged into a live destination, validated end to end, and finished with a routing flip - all without standing up a parallel migration stack.&lt;/p&gt;
&lt;h3 id=&quot;building-a-regional-multi-tenant-system&quot;&gt;Building a regional multi-tenant system?&lt;/h3&gt;
&lt;p&gt;If you’re building - or planning to build - a regional, multi-tenant data platform, the data mover is the component that decides whether your architecture can actually evolve. Check out &lt;a href=&quot;https://github.com/adiom-data/dsync&quot;&gt;Dsync&lt;/a&gt; for tenant data mobility, and reach out if you want help with tenant migrations - we’ve done this in production and can help you do it too.&lt;/p&gt;
&lt;p&gt;[&lt;/p&gt;
&lt;p&gt;Talk to the Dsync Team&lt;/p&gt;
&lt;p&gt;](&lt;a href=&quot;https://www.adiom.io/contact&quot;&gt;https://www.adiom.io/contact&lt;/a&gt;)&lt;/p&gt;
</content:encoded><category>engineering</category><category>replication</category><author>Alexander Komyagin</author></item><item><title>Migrating to Azure Cosmos DB: Why, How, and What to Expect</title><link>https://www.adiom.io/post/migrating-to-azure-cosmos-db-why-how-and-what-to-expect/</link><guid isPermaLink="true">https://www.adiom.io/post/migrating-to-azure-cosmos-db-why-how-and-what-to-expect/</guid><description>Before going further, it is worth being precise about names, because Azure&apos;s branding has been evolving over the years and can be somewhat confusing.</description><pubDate>Wed, 03 Jun 2026 05:42:00 GMT</pubDate><content:encoded>&lt;p&gt;If you’re optimizing your existing database stack or modernizing it to keep up with the times, you have probably already felt the pull toward a fully managed, AI-ready, and globally distributed database on Azure.&lt;/p&gt;
&lt;p&gt;Before going further, it is worth being precise about names, because Azure’s branding has been evolving over the years and can be somewhat confusing. Two distinct products are in play:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Azure Cosmos DB for NoSQL&lt;/strong&gt; - the native Cosmos DB engine and document API. This was &lt;strong&gt;originally launched as the “Cosmos DB SQL API”&lt;/strong&gt; (and Cosmos DB itself was briefly called “DocumentDB” back in 2014). The “SQL API” name persisted for years and still turns up in old docs and Stack Overflow answers - it refers to the &lt;em&gt;same thing&lt;/em&gt; now called Cosmos DB for NoSQL. It is not a relational database; the “SQL” only ever meant a SQL-like query dialect over JSON.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Azure DocumentDB (aka vCore)&lt;/strong&gt; - a MongoDB-compatible document database, powered by the &lt;strong&gt;open-source DocumentDB engine&lt;/strong&gt; (a PostgreSQL-based engine, MIT-licensed, open-sourced by Microsoft in January 2025) with full MongoDB wire-protocol compatibility. Microsoft now markets this as “Azure DocumentDB” in its own right. It is unrelated to Amazon’s separate “DocumentDB” product.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These are not interchangeable, and they compete with different things. This post keeps them separate throughout: &lt;strong&gt;why&lt;/strong&gt; teams migrate, &lt;strong&gt;how&lt;/strong&gt; each product works and stacks up, &lt;strong&gt;how&lt;/strong&gt; to run the migration, and &lt;strong&gt;who&lt;/strong&gt; has done it successfully.&lt;/p&gt;
&lt;h2 id=&quot;1-why-migrate-to-azure-cosmos-db&quot;&gt;1. Why Migrate to Azure Cosmos DB&lt;/h2&gt;
&lt;p&gt;The motivations split into three major categories: costs, removing operational burden, and unlocking capabilities that are impractical to build yourself.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Eliminating operational toil.&lt;/strong&gt; Self-managed NoSQL means owning sharding, replica-set failover, patching, backup verification, and capacity planning. Both products are fully managed - automatic maintenance, patching, and updates - with no application changes required.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Global distribution.&lt;/strong&gt; Cosmos DB for NoSQL offers turnkey global distribution: you add regions with a button, with active-active multi-region writes and automatic failover. This is the single hardest thing to replicate with a self-managed cluster. It is also the workload pattern OpenAI relies on - running ChatGPT’s product data on Cosmos DB with &lt;strong&gt;multi-region replication across dozens of regions&lt;/strong&gt; (more on that below).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;SLAs you can put in a contract.&lt;/strong&gt; Cosmos DB for NoSQL provides financially-backed SLAs covering availability, latency, throughput, &lt;em&gt;and&lt;/em&gt; consistency. Multi-region accounts are guaranteed &lt;strong&gt;99.999% availability&lt;/strong&gt;; Azure DocumentDB carries a &lt;strong&gt;99.99%&lt;/strong&gt; SLA. Cosmos DB for NoSQL delivers single-digit-millisecond response times and offers five well-defined consistency levels, letting teams tune the latency/consistency tradeoff explicitly.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Elastic scalability and cost control.&lt;/strong&gt; The NoSQL API supports three throughput models - standard provisioned, autoscale, and serverless (pay-per-request). There is a lifetime free tier (1000 RU/s + 25 GB), and Reserved Capacity offers up to 63% savings. One caveat: &lt;strong&gt;serverless accounts are single-region only&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Thesdsdds DocumentDB path for MongoDB shops.&lt;/strong&gt; For lift-and-shift from MongoDB, Azure DocumentDB is usually the better target than the older RU-based MongoDB API: &lt;strong&gt;predictable per-vCore pricing&lt;/strong&gt; rather than the harder-to-estimate RU model, rich aggregation-pipeline fidelity, and multi-cloud portability via standard MongoDB drivers and tooling.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The AI era - one database for operational data and vectors.&lt;/strong&gt; Microsoft now positions Cosmos DB explicitly as a “unified AI database”: document, vector, key-value, graph, and table data in one store. Integrated &lt;strong&gt;DiskANN&lt;/strong&gt; vector and hybrid similarity search lets teams keep embeddings next to operational data for RAG, AI agents, and LLM caching - avoiding a separate vector database.&lt;/p&gt;
&lt;h3 id=&quot;whats-new---azure-cosmos-db-conf-2026-april-28-2026&quot;&gt;What’s new - Azure Cosmos DB Conf 2026 (April 28, 2026)&lt;/h3&gt;
&lt;p&gt;The &lt;a href=&quot;https://developer.azurecosmosdb.com/conf/&quot;&gt;2026 Cosmos DB conference&lt;/a&gt; headlined several developments worth factoring into a migration decision:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Azure Cosmos DB Agent&lt;/strong&gt; - a built-in AI assistant with a growing catalog of skills for partition-key selection, data modeling, index design, and RU-consumption troubleshooting. This directly targets the hardest parts of a migration.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;MultiCloudDB SDK&lt;/strong&gt; (preview) - a portable Java SDK (“write once, run anywhere”) spanning Azure Cosmos DB, Amazon DynamoDB, and Google Cloud Spanner.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Azure DocumentDB - “one codebase, any cloud”&lt;/strong&gt; - deploy the open-source engine on-premises via Kubernetes or fully managed on Azure with no code rewrites.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Azure RBAC integration&lt;/strong&gt; for Cosmos DB entered private preview.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;AMD EPYC v7&lt;/strong&gt; infrastructure - up to &lt;strong&gt;35% more performance and performance-per-dollar&lt;/strong&gt; on the newest generation.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;OpenAI, Vercel, and Office Depot/ODP all presented; OpenAI’s Jonathan Lee described running “thousands of product tables on Azure Cosmos DB” with multi-region replication across dozens of regions.&lt;/p&gt;
&lt;h2 id=&quot;2-technical-details-and-how-it-compares&quot;&gt;2. Technical Details and How It Compares&lt;/h2&gt;
&lt;h3 id=&quot;shared-architecture-concepts&quot;&gt;Shared architecture concepts&lt;/h3&gt;
&lt;p&gt;Cosmos DB for NoSQL is built on a few core ideas:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Request Units (RUs).&lt;/strong&gt; CPU, memory, and IOPS are abstracted into a single throughput currency. Every operation costs a measurable number of RUs; billing follows RU/s plus storage. (Azure DocumentDB / vCore does &lt;strong&gt;not&lt;/strong&gt; use RUs = it bills on provisioned vCore tiers, which is part of its appeal.)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Partitioning.&lt;/strong&gt; Data is split into logical partitions by a chosen &lt;strong&gt;partition key&lt;/strong&gt;, mapped onto physical partitions (each ~50 GB and 10,000 RU/s). Picking a high-cardinality, evenly-accessed key is the single most important design decision. Hierarchical (sub-)partition keys handle high-cardinality and multi-tenant workloads.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Five consistency levels&lt;/strong&gt; - Strong, Bounded Staleness, Session, Consistent Prefix, Eventual. Session is the default; Strong gives RPO 0.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Change feed&lt;/strong&gt; - an ordered, persistent log of item changes (latest-version and all-versions-and-deletes modes), used for event-driven architectures and replication.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Note that &lt;strong&gt;Change Stream&lt;/strong&gt; in Azure Document DB is independent from Cosmos NoSQL change feed. It’s implemented on top of PostgreSQL WAL replication and still has some rough edges as of this writing - the Cosmos DB team is actively working on that.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;comparison-a---azure-documentdb-vcore-vs-mongodb-atlas-and-aws-documentdb&quot;&gt;Comparison A - Azure DocumentDB (vCore) vs. MongoDB Atlas and AWS DocumentDB&lt;/h3&gt;
&lt;p&gt;This is the relevant comparison if you run MongoDB today or planning to replatform a legacy database to MongoDB. All three databases speak the MongoDB wire protocol; the differences are &lt;strong&gt;price, access to premium storage, and native integrations&lt;/strong&gt;.&lt;/p&gt;
&lt;table class=&quot;_4FIAL&quot; data-hook=&quot;table-component&quot; style=&quot;border-spacing:0;border-collapse:separate&quot;&gt;&lt;colgroup&gt;&lt;col style=&quot;width:65px;min-width:65px&quot;&gt;&lt;col style=&quot;width:65px;min-width:65px&quot;&gt;&lt;col style=&quot;width:65px;min-width:65px&quot;&gt;&lt;col style=&quot;width:65px;min-width:65px&quot;&gt;&lt;/colgroup&gt;&lt;tbody&gt;&lt;tr style=&quot;height:auto&quot;&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;lbwdh358&quot; data-visual-col=&quot;0&quot; data-visual-row=&quot;0&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;div class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-kxa7m359&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;br role=&quot;presentation&quot;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;em3fl360&quot; data-visual-col=&quot;1&quot; data-visual-row=&quot;0&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-pr5fe361&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Azure DocumentDB (vCore)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;vy200363&quot; data-visual-col=&quot;2&quot; data-visual-row=&quot;0&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-0qqsc364&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;MongoDB Atlas&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;pl08k366&quot; data-visual-col=&quot;3&quot; data-visual-row=&quot;0&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:-0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;right:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-tl384367&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Amazon DocumentDB&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height:auto&quot;&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;akq4s370&quot; data-visual-col=&quot;0&quot; data-visual-row=&quot;1&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-79iw4371&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;strong style=&quot;font-weight:700&quot;&gt;&lt;span&gt;Pricing model&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;nnwet373&quot; data-visual-col=&quot;1&quot; data-visual-row=&quot;1&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-ghoks374&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Predictable per-vCore tiers + storage&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;72be0376&quot; data-visual-col=&quot;2&quot; data-visual-row=&quot;1&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-2f4d6377&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Compute + storage, premium at scale&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;zjoek379&quot; data-visual-col=&quot;3&quot; data-visual-row=&quot;1&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:-0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;right:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-adhwn380&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Instance-based + storage I/O&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height:auto&quot;&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;go5n3383&quot; data-visual-col=&quot;0&quot; data-visual-row=&quot;2&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-zuj58384&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;strong style=&quot;font-weight:700&quot;&gt;&lt;span&gt;Premium / high-perf storage&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;a65jv386&quot; data-visual-col=&quot;1&quot; data-visual-row=&quot;2&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-qfr2t387&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;NVMe-class tiers; DiskANN vector search&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;54taa389&quot; data-visual-col=&quot;2&quot; data-visual-row=&quot;2&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-nnud3390&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Workload-tiered storage&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;j3qog392&quot; data-visual-col=&quot;3&quot; data-visual-row=&quot;2&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:-0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;right:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-2njo1393&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;I/O-Optimized storage class&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height:auto&quot;&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;fs4nl396&quot; data-visual-col=&quot;0&quot; data-visual-row=&quot;3&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-arura397&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;strong style=&quot;font-weight:700&quot;&gt;&lt;span&gt;MongoDB feature parity&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;mdbp2399&quot; data-visual-col=&quot;1&quot; data-visual-row=&quot;3&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-ad5zp400&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;High and improving; open-source engine&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;e3w3o402&quot; data-visual-col=&quot;2&quot; data-visual-row=&quot;3&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-zimf5403&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Reference implementation - full parity&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;fmb0c405&quot; data-visual-col=&quot;3&quot; data-visual-row=&quot;3&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:-0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;right:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-kf3fy406&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Trails real MongoDB on version/features&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height:auto&quot;&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;cnn8i409&quot; data-visual-col=&quot;0&quot; data-visual-row=&quot;4&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-olupp410&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;strong style=&quot;font-weight:700&quot;&gt;&lt;span&gt;Native integrations&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;4agp3412&quot; data-visual-col=&quot;1&quot; data-visual-row=&quot;4&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-enz0i413&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Deep Azure (AI Foundry, Functions, AI Search, Entra ID)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;htsg5415&quot; data-visual-col=&quot;2&quot; data-visual-row=&quot;4&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-hrqlv416&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Cloud-agnostic; owns its own ecosystem&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;6xn1k418&quot; data-visual-col=&quot;3&quot; data-visual-row=&quot;4&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:-0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;right:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-2kzdh419&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Deep AWS (IAM, Lambda, etc.)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height:auto&quot;&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;1wgzx422&quot; data-visual-col=&quot;0&quot; data-visual-row=&quot;5&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-nz7nj423&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;strong style=&quot;font-weight:700&quot;&gt;&lt;span&gt;Availability SLA&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;03mzf425&quot; data-visual-col=&quot;1&quot; data-visual-row=&quot;5&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-b7fsf426&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;99.995%&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;qv07y428&quot; data-visual-col=&quot;2&quot; data-visual-row=&quot;5&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-eshu7429&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Tier-dependent&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;a8kna431&quot; data-visual-col=&quot;3&quot; data-visual-row=&quot;5&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:-0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;right:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-70mxr432&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Tier-dependent&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height:101px&quot;&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;tk2yy435&quot; data-visual-col=&quot;0&quot; data-visual-row=&quot;6&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;bottom:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-0l7m9436&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;strong style=&quot;font-weight:700&quot;&gt;&lt;span&gt;Lock-in&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;lir6k438&quot; data-visual-col=&quot;1&quot; data-visual-row=&quot;6&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;bottom:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-313ur439&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Engine open-source (MIT); service on Azure, multi-cloud on K8s, or on-prem&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;10g66441&quot; data-visual-col=&quot;2&quot; data-visual-row=&quot;6&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;bottom:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-qzp5i442&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Low - runs on any cloud or self-hosted&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;3jrth444&quot; data-visual-col=&quot;3&quot; data-visual-row=&quot;6&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:-0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;bottom:-0.5px;left:-0.5px;right:-0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;right:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-bzhv2445&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;High - AWS only&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The deciding factors are usually &lt;strong&gt;price and integration&lt;/strong&gt;. DocumentDB’s predictable per-vCore pricing is easier to forecast and often cheaper than Atlas, it gives you NVMe-class premium storage and integrated vector search, and it plugs natively into the Azure AI stack. Atlas wins on full MongoDB fidelity and cloud portability; AWS DocumentDB mainly makes sense if you are already all-in on AWS, though it lags on MongoDB feature parity.&lt;/p&gt;
&lt;h3 id=&quot;comparison-b---azure-cosmos-db-for-nosql-vs-dynamodb-and-cassandra&quot;&gt;Comparison B - Azure Cosmos DB for NoSQL vs. DynamoDB and Cassandra&lt;/h3&gt;
&lt;p&gt;This is the relevant comparison for greenfield, high-scale key-value/document workloads where you are &lt;em&gt;not&lt;/em&gt; tied to MongoDB.&lt;/p&gt;
&lt;table class=&quot;_4FIAL&quot; data-hook=&quot;table-component&quot; style=&quot;border-spacing:0;border-collapse:separate&quot;&gt;&lt;colgroup&gt;&lt;col style=&quot;width:65px;min-width:65px&quot;&gt;&lt;col style=&quot;width:65px;min-width:65px&quot;&gt;&lt;col style=&quot;width:65px;min-width:65px&quot;&gt;&lt;col style=&quot;width:65px;min-width:65px&quot;&gt;&lt;/colgroup&gt;&lt;tbody&gt;&lt;tr style=&quot;height:auto&quot;&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;r6q7i458&quot; data-visual-col=&quot;0&quot; data-visual-row=&quot;0&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;div class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-xmpyb459&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;br role=&quot;presentation&quot;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;ng9fz460&quot; data-visual-col=&quot;1&quot; data-visual-row=&quot;0&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-np0o5461&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Cosmos DB for NoSQL&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;oyvw2463&quot; data-visual-col=&quot;2&quot; data-visual-row=&quot;0&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-nvrgc464&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;AWS DynamoDB&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;8yrfz466&quot; data-visual-col=&quot;3&quot; data-visual-row=&quot;0&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:-0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;right:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-b4y5q467&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Apache Cassandra&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height:auto&quot;&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;mrwbn470&quot; data-visual-col=&quot;0&quot; data-visual-row=&quot;1&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-pbvbr471&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;strong style=&quot;font-weight:700&quot;&gt;&lt;span&gt;Model&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;rnyvl473&quot; data-visual-col=&quot;1&quot; data-visual-row=&quot;1&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-hitf6474&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Document, rich query/indexing&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;b1pdn476&quot; data-visual-col=&quot;2&quot; data-visual-row=&quot;1&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-shk4w477&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Key-value + document, thinner query model&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;379e8479&quot; data-visual-col=&quot;3&quot; data-visual-row=&quot;1&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:-0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;right:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-ef0yx480&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Wide-column, CQL&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height:auto&quot;&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;zq6jl483&quot; data-visual-col=&quot;0&quot; data-visual-row=&quot;2&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-7nxv9484&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;strong style=&quot;font-weight:700&quot;&gt;&lt;span&gt;Pricing&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;wtg78486&quot; data-visual-col=&quot;1&quot; data-visual-row=&quot;2&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-11ive487&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;RU/s (provisioned, autoscale, serverless) + storage&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;fzc9n489&quot; data-visual-col=&quot;2&quot; data-visual-row=&quot;2&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-e3p52490&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Capacity units / on-demand&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;zfeb5492&quot; data-visual-col=&quot;3&quot; data-visual-row=&quot;2&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:-0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;right:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-1ch9z493&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Self-managed infra cost&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height:auto&quot;&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;xqazn496&quot; data-visual-col=&quot;0&quot; data-visual-row=&quot;3&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-gfrz4497&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;strong style=&quot;font-weight:700&quot;&gt;&lt;span&gt;Global distribution&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;49jul499&quot; data-visual-col=&quot;1&quot; data-visual-row=&quot;3&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-smltc500&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Turnkey, multi-region multi-write&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;q88n0502&quot; data-visual-col=&quot;2&quot; data-visual-row=&quot;3&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-8cp4f503&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Global Tables&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;g0wv8505&quot; data-visual-col=&quot;3&quot; data-visual-row=&quot;3&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:-0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;right:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-5z8fb506&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Multi-datacenter, manual ops&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height:auto&quot;&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;ybd3l509&quot; data-visual-col=&quot;0&quot; data-visual-row=&quot;4&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-qho5v510&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;strong style=&quot;font-weight:700&quot;&gt;&lt;span&gt;Consistency&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;ywjva512&quot; data-visual-col=&quot;1&quot; data-visual-row=&quot;4&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-9ib2s513&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;5 tunable levels&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;ciwoq515&quot; data-visual-col=&quot;2&quot; data-visual-row=&quot;4&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-bkc2t516&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Eventual or strong&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;fviws518&quot; data-visual-col=&quot;3&quot; data-visual-row=&quot;4&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:-0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;right:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-4cn7w519&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Tunable per-query (quorum)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height:auto&quot;&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;vqu59522&quot; data-visual-col=&quot;0&quot; data-visual-row=&quot;5&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-jtipd523&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;strong style=&quot;font-weight:700&quot;&gt;&lt;span&gt;Operational model&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;895g7525&quot; data-visual-col=&quot;1&quot; data-visual-row=&quot;5&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-48o2z526&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Fully managed&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;qvo5v528&quot; data-visual-col=&quot;2&quot; data-visual-row=&quot;5&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-05a11529&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Fully managed&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;dttv3531&quot; data-visual-col=&quot;3&quot; data-visual-row=&quot;5&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:-0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;right:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-vzeyo532&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Self-managed unless using a managed offering (e.g. Astra DB, Azure Cassandra MI)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height:auto&quot;&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;9jpuf535&quot; data-visual-col=&quot;0&quot; data-visual-row=&quot;6&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;bottom:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-2jpfn536&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;strong style=&quot;font-weight:700&quot;&gt;&lt;span&gt;Lock-in&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;3iabu538&quot; data-visual-col=&quot;1&quot; data-visual-row=&quot;6&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;bottom:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-ebpb2539&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Azure only&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;ucb8y541&quot; data-visual-col=&quot;2&quot; data-visual-row=&quot;6&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;bottom:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-9fd47542&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;AWS only&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;1p8th544&quot; data-visual-col=&quot;3&quot; data-visual-row=&quot;6&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:-0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;bottom:-0.5px;left:-0.5px;right:-0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;right:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-dvr56545&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;None (open source)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Against DynamoDB, Cosmos DB for NoSQL’s distinguishing strengths are its richer query and indexing model and a five-level consistency spectrum (DynamoDB offers only two). Against self-managed Cassandra, the win is eliminating the operational burden of multi-datacenter clusters while keeping tunable consistency. Cosmos DB’s main downsides are Azure lock-in and an RU cost model that is notoriously hard to estimate up front. (Cosmos DB also offers a wire-compatible &lt;strong&gt;Cassandra API&lt;/strong&gt; - a common zero-downtime landing zone for existing Cassandra workloads; see the Symantec story below.)&lt;/p&gt;
&lt;h2 id=&quot;3-how-to-migrate&quot;&gt;3. How to Migrate&lt;/h2&gt;
&lt;p&gt;For brevity, in this post we frame a migration as three phases - &lt;strong&gt;pre-migration&lt;/strong&gt; (assessment and planning), &lt;strong&gt;migration&lt;/strong&gt; (moving data), and &lt;strong&gt;post-migration&lt;/strong&gt; (cutover and optimization). Well-executed planning is the single biggest predictor of a smooth migration - you can read more about that in our 5-series post &lt;a href=&quot;https://www.adiom.io/post/production-database-migration-or-modernization-a-comprehensive-planning-guide&quot;&gt;on migration planning&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;step-1---plan&quot;&gt;Step 1 - Plan&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Assess.&lt;/strong&gt; Inventory every database and collection with its name and data size. The Azure Cosmos DB Migration extension for VS Code assesses a MongoDB workload and flags unsupported features before you move anything.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Choose the target.&lt;/strong&gt; Azure DocumentDB for lift-and-shift from MongoDB; Cosmos DB for NoSQL for high-scale work.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Choose the partition/shard key.&lt;/strong&gt; This is the most important and &lt;em&gt;immutable&lt;/em&gt; decision - pick a key that distributes both storage and request volume evenly, and don’t blindly reuse your existing MongoDB shard key. (The new Cosmos DB Agent can help here.)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Capacity-plan.&lt;/strong&gt; For the NoSQL API, size RU/s with the capacity calculator or measure real query charges against sample data; pre-provision enough RU/s so Cosmos DB creates partitions ahead of ingestion. For vCore, pick the node tier.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;step-2---choose-tooling-and-migrate&quot;&gt;Step 2 - Choose tooling and migrate&lt;/h3&gt;
&lt;p&gt;The right tool depends on dataset size, downtime tolerance, &lt;strong&gt;and how hard it is to set up&lt;/strong&gt; - an underrated dimension, since complex tooling is itself a source of migration risk and delay.&lt;/p&gt;
&lt;table class=&quot;_4FIAL&quot; data-hook=&quot;table-component&quot; style=&quot;border-spacing:0;border-collapse:separate&quot;&gt;&lt;colgroup&gt;&lt;col style=&quot;width:65px;min-width:65px&quot;&gt;&lt;col style=&quot;width:65px;min-width:65px&quot;&gt;&lt;col style=&quot;width:65px;min-width:65px&quot;&gt;&lt;col style=&quot;width:65px;min-width:65px&quot;&gt;&lt;/colgroup&gt;&lt;tbody&gt;&lt;tr style=&quot;height:47px&quot;&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;rr3d6589&quot; data-visual-col=&quot;0&quot; data-visual-row=&quot;0&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-irmoc590&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Tool&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;l779d592&quot; data-visual-col=&quot;1&quot; data-visual-row=&quot;0&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-jalzb593&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Mode&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;munz1595&quot; data-visual-col=&quot;2&quot; data-visual-row=&quot;0&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-jhees596&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Ease of setup&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;ygj2u598&quot; data-visual-col=&quot;3&quot; data-visual-row=&quot;0&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:-0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;right:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-goxf1599&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Best for&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height:128px&quot;&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;0yf3y602&quot; data-visual-col=&quot;0&quot; data-visual-row=&quot;1&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-wx1t9603&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://docs.adiom.io/&quot; rel=&quot;noopener noreferrer&quot; class=&quot;Z5m1L N-2r5&quot; data-hook=&quot;web-link&quot;&gt;&lt;strong style=&quot;font-weight:700&quot;&gt;&lt;u style=&quot;text-decoration:underline&quot;&gt;&lt;span&gt;Adiom Dsync&lt;/span&gt;&lt;/u&gt;&lt;/strong&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;y9hrr605&quot; data-visual-col=&quot;1&quot; data-visual-row=&quot;1&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-tr50f606&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;strong style=&quot;font-weight:700&quot;&gt;&lt;span&gt;Online&lt;/span&gt;&lt;/strong&gt;&lt;span&gt; (continuous)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;cdn1z608&quot; data-visual-col=&quot;2&quot; data-visual-row=&quot;1&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-kmx60609&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;strong style=&quot;font-weight:700&quot;&gt;&lt;span&gt;Easy&lt;/span&gt;&lt;/strong&gt;&lt;span&gt; - even with horizontal scalability&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;ukxm9612&quot; data-visual-col=&quot;3&quot; data-visual-row=&quot;1&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:-0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;right:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-jb3ki613&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;strong style=&quot;font-weight:700&quot;&gt;&lt;span&gt;Production NoSQL migrations&lt;/span&gt;&lt;/strong&gt;&lt;span&gt; with minimal-downtime cutover&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height:128px&quot;&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;60t3y617&quot; data-visual-col=&quot;0&quot; data-visual-row=&quot;2&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-7dhhv618&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Native MongoDB tools (mongodump/mongorestore)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;j0yno620&quot; data-visual-col=&quot;1&quot; data-visual-row=&quot;2&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-rxsoh621&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Offline&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;o6sou623&quot; data-visual-col=&quot;2&quot; data-visual-row=&quot;2&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-5tok0624&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Easy&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;k5az2626&quot; data-visual-col=&quot;3&quot; data-visual-row=&quot;2&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:-0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;right:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-esqa5627&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;&amp;lt; 10 GB&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height:auto&quot;&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;li6wa630&quot; data-visual-col=&quot;0&quot; data-visual-row=&quot;3&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-su1a4631&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Azure Database Migration Service (DMS)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;qxii8633&quot; data-visual-col=&quot;1&quot; data-visual-row=&quot;3&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-8moh1634&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Online or offline&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;2jo2h636&quot; data-visual-col=&quot;2&quot; data-visual-row=&quot;3&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-kmwsv637&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Moderate - Premium tier often required&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;xxqnr639&quot; data-visual-col=&quot;3&quot; data-visual-row=&quot;3&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:-0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;right:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-yvv0b640&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;&amp;lt; 1 TB&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height:auto&quot;&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;t73rz643&quot; data-visual-col=&quot;0&quot; data-visual-row=&quot;4&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-kvqm1644&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Azure Data Factory&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;r1d1e646&quot; data-visual-col=&quot;1&quot; data-visual-row=&quot;4&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-ulk9h647&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Offline&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;9f68y649&quot; data-visual-col=&quot;2&quot; data-visual-row=&quot;4&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-v1hxu650&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Moderate&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;jfu7s652&quot; data-visual-col=&quot;3&quot; data-visual-row=&quot;4&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:-0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;right:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-flrjt653&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;&amp;gt; 1 TB&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height:auto&quot;&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;s1iew656&quot; data-visual-col=&quot;0&quot; data-visual-row=&quot;5&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-dvzn6657&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Azure Databricks + Spark&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;v5qkw659&quot; data-visual-col=&quot;1&quot; data-visual-row=&quot;5&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-vzzke660&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Online or offline&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;lqvou662&quot; data-visual-col=&quot;2&quot; data-visual-row=&quot;5&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-8joz4663&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Hard - requires custom code&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;advxb665&quot; data-visual-col=&quot;3&quot; data-visual-row=&quot;5&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:-0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;right:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-av0eg666&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Large datasets, custom transforms&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height:auto&quot;&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;ji7lq669&quot; data-visual-col=&quot;0&quot; data-visual-row=&quot;6&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;bottom:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-q9064670&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Cosmos DB Desktop Data Migration Tool&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;yapn6672&quot; data-visual-col=&quot;1&quot; data-visual-row=&quot;6&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;bottom:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-hdsk4673&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Offline&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;tjhwi675&quot; data-visual-col=&quot;2&quot; data-visual-row=&quot;6&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;bottom:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-1md9k676&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Easy&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;1qqc4678&quot; data-visual-col=&quot;3&quot; data-visual-row=&quot;6&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:-0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;bottom:-0.5px;left:-0.5px;right:-0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;right:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-0lrz2679&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span&gt;Cross-platform CLI use&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;For &lt;strong&gt;production&lt;/strong&gt; workloads - where you cannot afford an extended downtime window - &lt;a href=&quot;https://docs.adiom.io/&quot;&gt;&lt;strong&gt;Adiom’s Dsync&lt;/strong&gt;&lt;/a&gt; is the leading purpose-built tool for production NoSQL migrations. It performs an initial bulk copy followed by continuous change-data-capture replication, keeping source and target in sync so you can validate the target under real traffic and then cut over with minimal downtime. Critically, it is &lt;strong&gt;easy to set up&lt;/strong&gt; - and stays easy even when you scale it horizontally to move large datasets quickly. You can run it on your laptop to migrate 100’s of GB’s, or in your Kubernetes cluster to migrate 100’s of TBs. That combination of low setup friction and horizontal scalability is what sets it apart from the heavier built-in options, which trade setup complexity for capability.&lt;/p&gt;
&lt;p&gt;The built-in Azure options have constraints worth knowing: DMS online migrations require DMS instances in the &lt;strong&gt;Premium tier&lt;/strong&gt;, and are &lt;strong&gt;not supported against serverless&lt;/strong&gt; Cosmos DB accounts. For DocumentDB/vCore specifically, RU-to-vCore migration is GA and free from the Azure portal.&lt;/p&gt;
&lt;h3 id=&quot;step-3---online-migration-and-cutover&quot;&gt;Step 3 - Online migration and cutover&lt;/h3&gt;
&lt;p&gt;For minimal downtime, bulk-copy a snapshot, then continuously replicate changes until source and target converge - exactly the pattern Dsync automates. When replication lag is near zero, stop writes briefly, drain remaining changes, switch the application’s connection string, and cut over. Offline migration, by contrast, incurs downtime for the entire copy duration.&lt;/p&gt;
&lt;h3 id=&quot;step-4---post-migration-optimization&quot;&gt;Step 4 - Post-migration optimization&lt;/h3&gt;
&lt;p&gt;The only mandatory step is repointing your connection string - but cutting over before optimizing causes an immediate price/performance hit. Recommended:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Tune indexing.&lt;/strong&gt; Cosmos DB for MongoDB 3.6+ indexes only _id by default; the NoSQL API indexes everything automatically. Disable or minimize indexing &lt;em&gt;during&lt;/em&gt; bulk load, add indexes after.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Validate data&lt;/strong&gt;, configure global distribution (≥ 2 regions for HA), and set the consistency level (default: session).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Monitor&lt;/strong&gt; RU consumption via Azure Monitor and tune iteratively.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;4-success-stories&quot;&gt;4. Success Stories&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=CU10bYYjqPA&quot;&gt;&lt;strong&gt;OpenAI / ChatGPT.&lt;/strong&gt;&lt;/a&gt; The headline reference: &lt;em&gt;“OpenAI relies on Cosmos DB to dynamically scale their ChatGPT service – one of the fastest-growing consumer apps ever – enabling high reliability and low maintenance”&lt;/em&gt; (Satya Nadella). At Cosmos DB Conf 2026, OpenAI detailed running thousands of product tables on Cosmos DB with multi-region replication across dozens of regions - a proof point that the database scales with one of the most demanding consumer workloads on the planet.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Novo Nordisk — migrating off a relational database (2025).&lt;/strong&gt; A textbook cost-migration story: Novo Nordisk moved an application from an RDBMS setup costing &lt;strong&gt;~$280/month to Azure Cosmos DB at under $1/month&lt;/strong&gt; — while improving the end-user experience and reducing its carbon footprint. Presented at &lt;a href=&quot;https://devblogs.microsoft.com/cosmosdb/azure-cosmos-db-conf-2025-recap-ai-apps-scale/&quot;&gt;Cosmos DB Conf 2025&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Next - re-architecting for cost (2026).&lt;/strong&gt; The UK retailer faced escalating RU costs on a production workload. By redesigning &lt;strong&gt;partitioning, indexing, and query shape&lt;/strong&gt; — and moving from querying shared mutable state to event capture - Next &lt;strong&gt;cut its Cosmos DB costs by more than 60%&lt;/strong&gt; with no loss of performance or reliability. The lesson, per the presenter: “the issue wasn’t scale, it was design.” (&lt;a href=&quot;https://developer.microsoft.com/blog/azure-cosmos-db-conf-2026-recap-lessons-from-production&quot;&gt;Conf 2026 production recap&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Office Depot / The ODP Group - AI agent memory (2026).&lt;/strong&gt; ODP built an enterprise AI Personal Assistant on Azure Cosmos DB, using it as the &lt;strong&gt;agent memory layer&lt;/strong&gt; - per-user partitioned profiles and analytics. Employee adoption &lt;strong&gt;nearly doubled year-over-year&lt;/strong&gt;, with database scaling described as “hands-off” - no manual re-architecture as load grew. (&lt;a href=&quot;https://developer.microsoft.com/blog/azure-cosmos-db-conf-2026-recap-lessons-from-production&quot;&gt;Conf 2026 production recap&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.microsoft.com/en/customers/story/25353-kpmg-international-azure&quot;&gt;&lt;strong&gt;KPMG - agentic AI audit&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;(2025).&lt;/strong&gt; KPMG Clara AI uses Cosmos DB for chat history, session data, and agent memory. It serves &lt;strong&gt;95,000 auditors across 140+ countries&lt;/strong&gt; and processes petabytes of data annually - scale KPMG states would be impossible without Cosmos DB’s ability to deploy globally without re-architecting per jurisdiction.&lt;/p&gt;
&lt;h2 id=&quot;takeaways&quot;&gt;Takeaways&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Don’t get lost in the terminology: &lt;strong&gt;Cosmos DB for NoSQL&lt;/strong&gt; (the engine formerly branded the &lt;strong&gt;Cosmos DB SQL API&lt;/strong&gt;) versus &lt;strong&gt;Azure DocumentDB (vCore)&lt;/strong&gt;, built on the open-source DocumentDB engine.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Compare &lt;strong&gt;Azure DocumentDB against MongoDB Atlas and AWS DocumentDB&lt;/strong&gt; - the deciding factors are price, premium storage, and native integrations. Compare &lt;strong&gt;Cosmos DB for NoSQL against DynamoDB and Cassandra&lt;/strong&gt; - the wins are richer querying, tunable consistency, and managed global distribution.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The &lt;strong&gt;partition/shard key is immutable&lt;/strong&gt; - get key design and capacity planning right before moving a single document.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;For &lt;strong&gt;production&lt;/strong&gt; migrations, prefer continuous replication with a minimal-downtime cutover, and weigh &lt;strong&gt;ease of setup&lt;/strong&gt; alongside capability. &lt;strong&gt;Adiom’s Dsync&lt;/strong&gt; is purpose-built for this: easy to set up, horizontally scalable, and free of the offline-copy downtime that the built-in tools incur.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><category>guides</category><category>mongodb</category><category>cosmos-db</category><category>sql</category><category>documentdb</category><category>vector</category><author>Alexander Komyagin</author></item><item><title>Cassandra and New AKS-native Enterprise Offering</title><link>https://www.adiom.io/post/cassandra-and-new-aks-native-enterprise-offering/</link><guid isPermaLink="true">https://www.adiom.io/post/cassandra-and-new-aks-native-enterprise-offering/</guid><description>The Cassandra connectorThe Cassandra connector supports both source and sink roles, so you can migrate into and out of Cassandra-family databases.</description><pubDate>Thu, 21 May 2026 20:22:02 GMT</pubDate><content:encoded>&lt;p&gt;New Control Dashboard in Dsync Enterprise&lt;/p&gt;
&lt;p&gt;We’re excited to share two releases that go hand in hand: a new &lt;strong&gt;Cassandra connector&lt;/strong&gt; in private preview, and a fully &lt;strong&gt;AKS-native edition of Dsync Enterprise&lt;/strong&gt;, now available on the &lt;a href=&quot;https://marketplace.microsoft.com/en-us/product/container/adiom.adiom_dsync_container?tab=Overview&quot;&gt;Azure Marketplace&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;the-cassandra-connector&quot;&gt;The Cassandra connector&lt;/h2&gt;
&lt;p&gt;The Cassandra connector supports both &lt;strong&gt;source and sink&lt;/strong&gt; roles, so you can migrate &lt;strong&gt;into&lt;/strong&gt; and &lt;strong&gt;out of&lt;/strong&gt; Cassandra-family databases. It works with Apache Cassandra, &lt;em&gt;DataStax Enterprise&lt;/em&gt;, and &lt;em&gt;Astra DB&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;That opens up a set of migration paths customers have been asking us for:&lt;/p&gt;
&lt;p&gt;- &lt;em&gt;Apache Cassandra / Astra DB / DataStax Enterprise → Azure Managed Instance for Apache Cassandra&lt;/em&gt; - a homogeneous lift to a managed service.&lt;/p&gt;
&lt;p&gt;- &lt;em&gt;Apache Cassandra / Astra DB / DataStax Enterprise → MongoDB Atlas&lt;/em&gt; - a heterogeneous move to a document model.&lt;/p&gt;
&lt;p&gt;As with the rest of Dsync, these are &lt;strong&gt;live migrations&lt;/strong&gt;: data flows continuously from source to destination, so you can cut over on your schedule instead of the migration’s. And with Dsync Enterprise the migration &lt;em&gt;scales linearly&lt;/em&gt; with the number of workers, so you can migrate 10&lt;strong&gt;TB&lt;/strong&gt; with the same ease as 10GB.&lt;/p&gt;
&lt;h2 id=&quot;why-an-aks-native-offering&quot;&gt;Why an AKS-native offering&lt;/h2&gt;
&lt;p&gt;Cassandra deployments aren’t small. A typical cluster holds &lt;em&gt;terabytes of data and billions of records&lt;/em&gt;, and that scale is exactly where migrations get hard. For workloads like these, customers reach for &lt;a href=&quot;https://docs.adiom.io/enterprise/scalable-deployment&quot;&gt;&lt;em&gt;Dsync Enterprise&lt;/em&gt;&lt;/a&gt;, which is built to scale horizontally.&lt;/p&gt;
&lt;p&gt;The challenge was deployment. Standing up and operating a scalable migration tool shouldn’t be a project of its own. So we built a &lt;strong&gt;fully AKS-native offering&lt;/strong&gt; and published it on the &lt;a href=&quot;https://marketplace.microsoft.com/en-us/product/container/adiom.adiom_dsync_container?tab=Overview&quot;&gt;Azure Marketplace&lt;/a&gt;. It deploys straight into Kubernetes, regular or Automatic, - and if you’re not on Azure, the same release ships as a &lt;em&gt;Helm chart&lt;/em&gt; for any Kubernetes cluster.&lt;/p&gt;
&lt;h2 id=&quot;whats-new-in-dsync-enterprise&quot;&gt;What’s new in Dsync Enterprise&lt;/h2&gt;
&lt;p&gt;The AKS-native release also introduces a &lt;em&gt;web control dashboard&lt;/em&gt; for setting up and operating migrations:&lt;/p&gt;
&lt;p&gt;- &lt;em&gt;Manage multiple concurrent flows&lt;/em&gt; from a single deployment - no redeploying to add a migration.&lt;/p&gt;
&lt;p&gt;- &lt;em&gt;Dynamically allocate worker nodes&lt;/em&gt; to each flow, and &lt;em&gt;scale them up and down&lt;/em&gt; natively in Kubernetes as the workload changes.&lt;/p&gt;
&lt;p&gt;- &lt;em&gt;Test your flows and transformations ahead of time&lt;/em&gt;, so you can validate your configuration before moving production data.&lt;/p&gt;
&lt;p&gt;You control worker allocation per flow from the Web UI, which means one Dsync deployment can run a fleet of migrations side by side.&lt;/p&gt;
&lt;h3 id=&quot;more-than-cassandra&quot;&gt;More than Cassandra&lt;/h3&gt;
&lt;p&gt;The AKS-native offering features &lt;a href=&quot;https://docs.adiom.io/enterprise/scalable-deployment&quot;&gt;Dsync Enterprise&lt;/a&gt; and includes several private-preview connectors as a bonus. Beyond the Cassandra paths above, common routes include:&lt;/p&gt;
&lt;p&gt;- MongoDB Atlas / Community → Azure DocumentDB&lt;/p&gt;
&lt;p&gt;- Cosmos DB → MongoDB Atlas&lt;/p&gt;
&lt;p&gt;- AWS DocumentDB → Azure DocumentDB or MongoDB Atlas&lt;/p&gt;
&lt;p&gt;- DynamoDB → Cosmos DB NoSQL or MongoDB Atlas&lt;/p&gt;
&lt;p&gt;- Apache HBase → MongoDB, DocumentDB, or Cosmos DB NoSQL&lt;/p&gt;
&lt;p&gt;- PostgreSQL → DocumentDB or MongoDB Atlas&lt;/p&gt;
&lt;p&gt;- SQL Server → MongoDB, DocumentDB, or Cosmos DB NoSQL&lt;/p&gt;
&lt;p&gt;- DB2 → DocumentDB or MongoDB Atlas&lt;/p&gt;
&lt;p&gt;- Oracle → DocumentDB or MongoDB Atlas&lt;/p&gt;
&lt;p&gt;For the full list of supported connectors, see our &lt;a href=&quot;https://docs.adiom.io&quot;&gt;documentation&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;why-teams-choose-dsync&quot;&gt;Why teams choose Dsync&lt;/h2&gt;
&lt;p&gt;Adiom Dsync is the fastest, easiest, and most reliable way to move production workloads at scale — for RDBMS and NoSQL databases, in homogeneous or heterogeneous configurations. It’s purpose-built for mission-critical migrations:&lt;/p&gt;
&lt;p&gt;- &lt;em&gt;Accelerated timelines&lt;/em&gt; - complete online migrations in minutes to hours, not weeks or months, with native horizontal scaling in AKS.&lt;/p&gt;
&lt;p&gt;- &lt;em&gt;Enterprise-grade reliability&lt;/em&gt; - built-in resiliency and data validation reduce risk and prevent interruptions.&lt;/p&gt;
&lt;p&gt;- &lt;em&gt;Zero-storage transfer&lt;/em&gt; - data flows directly from source to destination with network encryption and no intermediate storage.&lt;/p&gt;
&lt;p&gt;- &lt;em&gt;Effortless deployment&lt;/em&gt; - no extra infrastructure to manage; monitor progress via CLI or web UI with full operational transparency.&lt;/p&gt;
&lt;p&gt;- &lt;em&gt;Expert guidance&lt;/em&gt; - tap into our deep experience with the process and the technology for a smooth, predictable migration.&lt;/p&gt;
&lt;h2 id=&quot;getting-started&quot;&gt;Getting started&lt;/h2&gt;
&lt;p&gt;Dsync can deploy into your existing &lt;em&gt;AKS cluster&lt;/em&gt; (regular or Automatic), or you can create a new cluster as part of the offer setup. All you need is a VNet from which both the source and destination databases are reachable.&lt;/p&gt;
&lt;p&gt;- &lt;strong&gt;Get the offer:&lt;/strong&gt; &lt;a href=&quot;https://marketplace.microsoft.com/en-us/product/container/adiom.adiom_dsync_container?tab=Overview&quot;&gt;Adiom Dsync on the Azure Marketplace&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;- &lt;strong&gt;Enterprise deployment docs:&lt;/strong&gt; &lt;a href=&quot;https://docs.adiom.io/enterprise/scalable-deployment&quot;&gt;https://docs.adiom.io/enterprise/scalable-deployment&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;- &lt;strong&gt;AKS-native deployment details:&lt;/strong&gt; &lt;a href=&quot;https://docs.adiom.io/enterprise/running-dsynct/azure-marketplace&quot;&gt;https://docs.adiom.io/enterprise/running-dsynct/azure-marketplace&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The Cassandra connector is in &lt;em&gt;private preview&lt;/em&gt; today. &lt;a href=&quot;https://www.adiom.io/contact&quot;&gt;Contact us&lt;/a&gt; for a migration assessment, help with setup, and a customized private offer.&lt;/p&gt;
</content:encoded><category>product</category><category>mongodb</category><category>cosmos-db</category><category>dynamodb</category><category>sql</category><category>hbase</category><author>Alexander Komyagin</author></item><item><title>Mission-Critical DB Migrations Are Heart Surgery. Treat Them That Way.</title><link>https://www.adiom.io/post/mission-critical-db-migrations-are-heart-surgery-treat-them-that-way/</link><guid isPermaLink="true">https://www.adiom.io/post/mission-critical-db-migrations-are-heart-surgery-treat-them-that-way/</guid><description>Most engineering teams wildly under- or overestimate what a large database migration actually takes.</description><pubDate>Thu, 16 Apr 2026 22:13:37 GMT</pubDate><content:encoded>&lt;p&gt;Most engineering teams wildly under- or overestimate what a large database migration actually takes. Here’s the honest picture - and why the right tooling is the difference between months and years.&lt;/p&gt;
&lt;h2 id=&quot;two-wrong-opinions-one-real-problem&quot;&gt;Two Wrong Opinions, One Real Problem&lt;/h2&gt;
&lt;p&gt;Ask an engineering or business unit leader what a database migration involves and you’ll almost always land on one of two extremes. Either they think it’s trivially easy - “just run it once in production” - or they treat it as some mythical, unknowable risk that gets endlessly deferred. In both cases, the result is the same: the can gets kicked down the road.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“Just run it once in production” is not a migration strategy. It’s a hope dressed up as a plan.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The misconception is partly understandable. Most leaders have only witnessed a handful of migrations in their careers, if any. And the range of what “a migration” can mean is enormous - which is exactly where the confusion starts.&lt;/p&gt;
&lt;h2 id=&quot;small-migrations-vs-mission-critical-ones&quot;&gt;Small Migrations vs. Mission-Critical Ones&lt;/h2&gt;
&lt;p&gt;Not every migration is equal. Small migrations - think under 100GB for non-critical internal services like dashboards or analytics tools - are genuinely fast and low-risk. They can often be completed in a single day with minimal preparation and even less organizational anxiety. These are routine procedures.&lt;/p&gt;
&lt;p&gt;Large migrations for revenue-generating, customer-facing systems are something else entirely. They are, without exaggeration, like heart surgery. The stakes are high. Precision is non-negotiable. And the confidence to execute comes not from luck or seniority, but from the ability to consistently and repeatably run the process in production - with the right instruments in hand.&lt;/p&gt;
&lt;p&gt;There’s a reason surgical teams don’t operate with improvised tools. A scalpel alone, versus access to a &lt;a href=&quot;https://www.intuitive.com/en-us/products-and-services/da-vinci/xi&quot;&gt;da Vinci Xi robotic system&lt;/a&gt;, represents not just a difference in capability but a difference in the outcomes that are even possible. The same logic applies here.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Flowchart illustrating the comprehensive planning for database migration with 7 steps, detailed activities and feedback loops, and text explaining each phase.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1408&quot; height=&quot;768&quot; src=&quot;/_astro/01.D7_GQNdh_2aaHm7.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Production migrations get complicated because of feedback loops between activities&lt;/p&gt;
&lt;h2 id=&quot;what-a-live-production-migration-actually-requires&quot;&gt;What a Live Production Migration Actually Requires&lt;/h2&gt;
&lt;p&gt;To execute a live database migration in production without taking your system offline, you need to coordinate a surprising number of moving parts simultaneously:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Parallelize data copy&lt;/strong&gt; - copying terabytes sequentially is impractical; concurrency is essential.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Coordinate initial sync and CDC&lt;/strong&gt; - Change Data Capture must seamlessly bridge the gap between the initial snapshot and live writes.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Maintain data integrity&lt;/strong&gt; - every row must land correctly, every relationship intact, every constraint respected.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Be able to rollback&lt;/strong&gt; - if something breaks, you need a clean, practiced path back. No improvising at 2am.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Account for source and destination specifics&lt;/strong&gt; - edge cases, encoding differences, type mismatches, and engine-specific behaviors all need handling.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Handle legacy and “ghost” records&lt;/strong&gt; - production databases accumulate years of orphaned rows, deprecated schemas, and soft-deleted data that can break assumptions.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;None of this is optional. Miss any one of them and you risk data loss, extended downtime, or a failed cutover window with the entire business watching.&lt;/p&gt;
&lt;h3 id=&quot;what-good-tooling-provides&quot;&gt;What Good Tooling Provides&lt;/h3&gt;
&lt;table class=&quot;_4FIAL&quot; data-hook=&quot;table-component&quot; style=&quot;border-spacing:0;border-collapse:separate&quot;&gt;&lt;colgroup&gt;&lt;col style=&quot;width:65px;min-width:65px&quot;&gt;&lt;col style=&quot;width:65px;min-width:65px&quot;&gt;&lt;/colgroup&gt;&lt;tbody&gt;&lt;tr style=&quot;height:47px&quot;&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;9j1gy12407&quot; data-visual-col=&quot;0&quot; data-visual-row=&quot;0&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-owkos12882&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span style=&quot;color:rgb(85, 206, 103);text-decoration:inherit&quot;&gt;&lt;span&gt;✓&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;Resumability&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;pkw1t12409&quot; data-visual-col=&quot;1&quot; data-visual-row=&quot;0&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:-0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;right:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-346iw13296&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span style=&quot;color:rgb(85, 206, 103);text-decoration:inherit&quot;&gt;&lt;span&gt;✓&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;Data integrity checks&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height:47px&quot;&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;hfagt12412&quot; data-visual-col=&quot;0&quot; data-visual-row=&quot;1&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-2h0qb12987&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span style=&quot;color:rgb(85, 206, 103);text-decoration:inherit&quot;&gt;&lt;span&gt;✓&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;Observability&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;6uxao12414&quot; data-visual-col=&quot;1&quot; data-visual-row=&quot;1&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:-0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;right:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-4vkmu13403&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span style=&quot;color:rgb(85, 206, 103);text-decoration:inherit&quot;&gt;&lt;span&gt;✓&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;Transformations&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height:47px&quot;&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;s1k3q12417&quot; data-visual-col=&quot;0&quot; data-visual-row=&quot;2&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-vskrk13092&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span style=&quot;color:rgb(85, 206, 103);text-decoration:inherit&quot;&gt;&lt;span&gt;✓&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;Security&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;z79yn12419&quot; data-visual-col=&quot;1&quot; data-visual-row=&quot;2&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:-0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;right:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-siqqd13510&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span style=&quot;color:rgb(85, 206, 103);text-decoration:inherit&quot;&gt;&lt;span&gt;✓&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;Ease of use&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height:47px&quot;&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;67h6612422&quot; data-visual-col=&quot;0&quot; data-visual-row=&quot;3&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;bottom:-0.5px;left:-0.5px;right:0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-dqyth13197&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span style=&quot;color:rgb(85, 206, 103);text-decoration:inherit&quot;&gt;&lt;span&gt;✓&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;Scalability&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;td data-hook=&quot;table-plugin-cell&quot; data-node-id=&quot;k3hwa12424&quot; data-visual-col=&quot;1&quot; data-visual-row=&quot;3&quot; class=&quot;bjDRJ&quot;&gt;&lt;div style=&quot;position:absolute;top:-0.5px;left:-0.5px;right:-0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;bottom:-0.5px;left:-0.5px;right:-0.5px;height:1px;background-color:var(--ricos-internal-table-border-color);z-index:101;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;left:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div style=&quot;position:absolute;top:0.5px;bottom:0.5px;right:-0.5px;width:1px;background-color:var(--ricos-internal-table-border-color);z-index:100;pointer-events:none&quot;&gt;&lt;/div&gt;&lt;div class=&quot;qOmV- HSYQU&quot;&gt;&lt;p class=&quot;rKr3c LXM-U _8Fwvf GywVr&quot; dir=&quot;auto&quot; id=&quot;viewer-hoq2813617&quot; tabindex=&quot;-1&quot;&gt;&lt;span class=&quot;jpwv0&quot;&gt;&lt;span style=&quot;color:rgb(85, 206, 103);text-decoration:inherit&quot;&gt;&lt;span&gt;✓&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;Extensibility for schema changes&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;repeatability-is-the-real-metric&quot;&gt;Repeatability Is the Real Metric&lt;/h2&gt;
&lt;p&gt;Perhaps the least intuitive part of a major migration project is how many times you need to run the full process before you actually touch production for real. The answer is: a lot.&lt;/p&gt;
&lt;p&gt;First, the migration runs repeatedly in lower environments - dev, staging, UAT - to calibrate the process, catch edge cases, and establish baseline performance metrics. These runs let you extrapolate how long the production migration will take and what can go wrong. Then come production dry runs: full end-to-end rehearsals, everything except the final cutover flip.&lt;/p&gt;
&lt;p&gt;Cutovers themselves are tightly choreographed events. They happen during off-peak windows, require all hands on deck, and are followed by stabilization periods of at least one to two weeks where the team monitors closely for regressions. Business units can only offer these windows a few times a year. There’s no wasted attempts budget.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;The repeatability and predictability of your migration tooling essentially define how long the project takes - and when you can actually cut over.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;why-we-built-dsync&quot;&gt;Why We Built Dsync&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/adiom-data/dsync/&quot;&gt;Dsync&lt;/a&gt; is our answer to the question: what does the robotic surgical platform look like for database migrations? It’s not a one-click migration service - the expertise and decision-making still lives with your team. But it meaningfully changes the probability of a successful outcome and compresses the timeline from something measured in calendar years to something measured in weeks.&lt;/p&gt;
&lt;p&gt;Before you can commit to a large migration project, you need months of feasibility assessment just to answer whether it’s even possible and what risks you’re taking on. Dsync shortens that runway significantly, giving teams the observability, resumability, and integrity checks needed to build confidence fast - and the extensibility to handle whatever surprises your production schema has been hiding for the last decade.&lt;/p&gt;
&lt;p&gt;We’re working toward a more automated future. But even today, having the right platform under you is the difference between a migration that drags on for a year of organizational anxiety and one that’s done before the next planning cycle.&lt;/p&gt;
&lt;h2 id=&quot;ready-to-treat-your-next-migration-like-the-surgery-it-is&quot;&gt;Ready to treat your next migration like the &lt;em&gt;surgery it is?&lt;/em&gt;&lt;/h2&gt;
&lt;p&gt;[&lt;/p&gt;
&lt;p&gt;Talk to the Dsync team →&lt;/p&gt;
&lt;p&gt;](&lt;a href=&quot;https://www.adiom.io/contact&quot;&gt;https://www.adiom.io/contact&lt;/a&gt;)&lt;/p&gt;
</content:encoded><category>strategy</category><category>replication</category><author>Alexander Komyagin</author></item><item><title>New SQL Connectors in Public Preview</title><link>https://www.adiom.io/post/new-sql-connectors-in-public-preview/</link><guid isPermaLink="true">https://www.adiom.io/post/new-sql-connectors-in-public-preview/</guid><description>We&apos;re excited to share that support for SQL Server, Oracle, and PostgreSQL via our SQLBatch connector is now in public preview.</description><pubDate>Mon, 09 Mar 2026 18:02:55 GMT</pubDate><content:encoded>&lt;p&gt;We’re excited to share that support for SQL Server, Oracle, and PostgreSQL via our SQLBatch connector is now in &lt;strong&gt;public preview&lt;/strong&gt;. The SQLBatch connector supports &lt;strong&gt;both initial sync and CDC&lt;/strong&gt; (all query-based), and is available in our Open Source Dsync. Check it out on &lt;a href=&quot;https://github.com/adiom-data/dsync/&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;usage&quot;&gt;Usage&lt;/h2&gt;
&lt;p&gt;The SQLBatch connector accepts a YAML configuration file with user-defined SQL queries declaring “virtual namespaces” to be migrated:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;driver: sqlserver  # or oracle, postgres&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;connectionstring: sqlserver://user:password@host:port?database=DbName&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;mappings:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  - namespace: db.users&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    query: &quot;SELECT id, name, email FROM users&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    partitionquery: &quot;SELECT id FROM users WHERE id % 4 = 0 ORDER BY id&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    cols: [id]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    limit: 1000&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    changes:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      - initialcursorquery: &quot;SELECT MAX(updated_at) FROM users&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        query: &quot;SELECT id, &apos;U&apos;, updated_at FROM users WHERE updated_at &amp;gt; $1 ORDER BY updated_at LIMIT 1000&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        interval: 5s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Each virtual namespace has the following key properties:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Unique name&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Query to get the full count&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Query to partition the dataset&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Query to retrieve the objects&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;One or more Change Tracking queries&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;One for the main table and one per each embedded object&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To start Dsync with the SQLBatch connector and the config saved in cfg.yml:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;dsync&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; sqlbatch&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --config=cfg.yml&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; /dev/null&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --log-json&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A complete example for migrating or syncing the sample Microsoft AdventureWorks database from SQL Server to Cosmos DB for NoSQL is available &lt;a href=&quot;https://github.com/alex-thc/mssql-to-cosmos-nosql-adventureworks&quot;&gt;in the AdventureWorks sample repository&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Read more about the connector usage in the &lt;a href=&quot;https://docs.adiom.io/reference/connectors/sql-batch&quot;&gt;docs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To help &lt;strong&gt;create or bootstrap the config file&lt;/strong&gt; you can use your &lt;strong&gt;favorite AI coding agent&lt;/strong&gt; (like Claude Code, Codex, Gemini or &lt;a href=&quot;http://Factory.AI&quot;&gt;Factory.AI&lt;/a&gt; Droid) with the Skills framework, or by &lt;strong&gt;converting MongoDB’s Relational Migrator mappings&lt;/strong&gt; using our AI Agent. Both assets will be published soon but feel free to &lt;a href=&quot;https://www.adiom.io/contact&quot;&gt;contact us&lt;/a&gt; in the meantime if you need them.&lt;/p&gt;
&lt;p&gt;Note that the Open Source version of Dsync only supports a single namespace for CDC. For CDC with multiple namespace consider our &lt;a href=&quot;https://docs.adiom.io/enterprise/running-dsynct/running-dsynct&quot;&gt;&lt;strong&gt;Enterprise&lt;/strong&gt;&lt;/a&gt; &lt;a href=&quot;https://docs.adiom.io/enterprise/running-dsynct/running-dsynct&quot;&gt;version&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;how-it-works&quot;&gt;How it works&lt;/h2&gt;
&lt;h3 id=&quot;dialects&quot;&gt;Dialects&lt;/h3&gt;
&lt;p&gt;In the SQLBatch connector, dialects or drivers abstract away the differences between SQL database vendors (SQL Server, PostgreSQL, DB2, etc.). Each dialect handles:&lt;/p&gt;
&lt;p&gt;1. SQL syntax variations - Different databases use different syntax for pagination (LIMIT vs TOP), string concatenation, date functions, etc.&lt;/p&gt;
&lt;p&gt;2. Data type mappings - How native types (e.g., NVARCHAR, BIGINT, DATETIME2) translate to the target document store&lt;/p&gt;
&lt;p&gt;3. CDC mechanisms - Change Data Capture works differently across databases (SQL Server uses CT/CDC tables, PostgreSQL uses logical replication slots, DB2 uses journals)&lt;/p&gt;
&lt;p&gt;4. Query generation - The dialect generates vendor-specific queries for initial loads and incremental syncs&lt;/p&gt;
&lt;p&gt;When you configure a SQLBatch source, you specify the dialect (e.g., driver: sqlserver or driver: postgres), and the connector uses the appropriate SQL generation and type conversion logic for that database platform.&lt;/p&gt;
&lt;h3 id=&quot;denormalization&quot;&gt;Denormalization&lt;/h3&gt;
&lt;p&gt;The connector uses a user-defined query to denormalize the data at the source. Most recent versions of major SQL database vendors do a great job at supporting JSON, and their query engines are able to perform complex JOINs much more efficiently than any streaming processor.&lt;/p&gt;
&lt;p&gt;For additional transformations beyond what RDMBS can do, such as converting JSON into native BSON types, Dsync supports extensible &lt;a href=&quot;https://docs.adiom.io/enterprise/running-dsynct/data-transformations&quot;&gt;transformers&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;change-tracking--cdc&quot;&gt;Change Tracking / CDC&lt;/h3&gt;
&lt;p&gt;The SQLBatch connector relies on a change tracking (CT) query and a configurable polling interval to determine what objects have changed at the source. Since the final JSON objects are often composed from several tables, the connector supports multiple CT queries per namespace - one for each of the source tables that are embedded in the object.&lt;/p&gt;
&lt;p&gt;The modified or deleted objects are then efficiently refetched using the main query in batches - hence the name “SQLBatch”. Compared to WAL-based log parsing, our approach allows us to &lt;strong&gt;eliminate a whole class of possible data integrity issues&lt;/strong&gt;, require &lt;strong&gt;no custom software on database servers&lt;/strong&gt;, and only needing &lt;strong&gt;regular read access&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;At Adiom, we’re making usually complex and messy data migration and replication easy. You can check the SQLBatch connector out on &lt;a href=&quot;https://github.com/adiom-data/dsync/&quot;&gt;GitHub&lt;/a&gt; and read more about its usage in the &lt;a href=&quot;https://docs.adiom.io/reference/connectors/sql-batch&quot;&gt;docs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We also have &lt;strong&gt;DB2 support&lt;/strong&gt; for SQLBatch available in Private Preview.  &lt;a href=&quot;https://www.adiom.io/contact&quot;&gt;Contact us&lt;/a&gt; to request access.&lt;/p&gt;
</content:encoded><category>product</category><category>mongodb</category><category>cosmos-db</category><category>sql</category><category>replication</category><author>Alexander Komyagin</author></item><item><title>[Part 5] Production Database Migration or Modernization: A Comprehensive Planning Guide</title><link>https://www.adiom.io/post/part-5-production-database-migration-or-modernization-a-comprehensive-planning-guide/</link><guid isPermaLink="true">https://www.adiom.io/post/part-5-production-database-migration-or-modernization-a-comprehensive-planning-guide/</guid><description>In this fifth and the final post in our guide, we will cover a sample database migration project plan and will discuss the key lessons learned based on our extensive experiences with 10GB to 100TB+ migrations.We highly recommend reading the previous posts in the series:Part 1 - Migration Readiness…</description><pubDate>Wed, 18 Feb 2026 17:20:50 GMT</pubDate><content:encoded>&lt;p&gt;In this fifth and the final post in our guide, we will cover a sample database migration project plan and will discuss the key lessons learned based on our extensive experiences with 10GB to 100TB+ migrations.&lt;/p&gt;
&lt;p&gt;We highly recommend reading the previous posts in the series:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.adiom.io/post/production-database-migration-or-modernization-a-comprehensive-planning-guide&quot;&gt;Part 1 - Migration Readiness and Key Factors Influencing Timeline and Risk&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.adiom.io/post/part-2-production-database-migration-or-modernization-a-comprehensive-planning-guide&quot;&gt;Part 2 - Downtime Strategy Options and Migration Tools&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.adiom.io/post/part-3-production-database-migration-or-modernization-a-comprehensive-planning-guide&quot;&gt;Part 3 -&lt;/a&gt; &lt;a href=&quot;https://www.adiom.io/post/part-3-production-database-migration-or-modernization-a-comprehensive-planning-guide&quot;&gt;Migration Planning and Post-Migration Validation Strategy&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.adiom.io/post/part-4-production-database-migration-or-modernization-a-comprehensive-planning-guide&quot;&gt;Part 4 -&lt;/a&gt; &lt;a href=&quot;https://www.adiom.io/post/part-4-production-database-migration-or-modernization-a-comprehensive-planning-guide&quot;&gt;Common Complications and Best Practices&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;9-sample-migration-plan-rdbms-to-nosql&quot;&gt;9. Sample Migration Plan: RDBMS to NoSQL&lt;/h2&gt;
&lt;p&gt;To “ground” the concepts that we discussed in past posts, let’s describe a realistic migration example:&lt;/p&gt;
&lt;h3 id=&quot;scenario-overview&quot;&gt;Scenario Overview&lt;/h3&gt;
&lt;p&gt;A financial services company operates a backend API service with these characteristics:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;220GB relational database with 12 tables&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Java monolith using Hibernate with tight database coupling in places&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Several dozen API endpoints supporting web and mobile clients&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Nightly batch jobs and Databricks data pipelines&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Event streaming via Kafka for some of the operations&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Data must be denormalized for the target NoSQL database, no stored procedures or triggers currently in use.&lt;/p&gt;
&lt;p&gt;The service is busy during banking hours (6am-6pm), otherwise mostly idle except for heavy batch jobs around 3am. Of course, this being a banking client, there’s exactly &lt;strong&gt;zero tolerance for data integrity issues&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;They’ve selected a NoSQL database for better horizontal scalability and chosen &lt;a href=&quot;https://adiom.io&quot;&gt;Adiom’s Dsync&lt;/a&gt; for migration based on its RDBMS to NoSQL transformation capabilities and CDC support.&lt;/p&gt;
&lt;h3 id=&quot;phase-1-planning-and-design-2-4-weeks-extended-to-6-7-weeks&quot;&gt;Phase 1: Planning and Design (2-4 weeks, extended to 6-7 weeks)&lt;/h3&gt;
&lt;p&gt;Initial timeline: 2-4 weeks.&lt;/p&gt;
&lt;p&gt;The team begins by mapping the current relational schema to a denormalized NoSQL model, identifying which tables should become embedded documents versus separate collections.&lt;/p&gt;
&lt;p&gt;Architecture review board approval, vendor consultant coordination, and executive stakeholder presentations generally consume more time than anticipated.&lt;/p&gt;
&lt;p&gt;Network constraints surface during planning - the source database sits in an on-premises data center while the target will be Cloud-based, requiring careful private link configuration and security review.&lt;/p&gt;
&lt;p&gt;Based on the initial testing, Dsync can migrate their 220GB database in approximately 4 hours, enabling a straightforward weekend migration window with a sufficient user notification. Dsync’s CDC capabilities mean they don’t need to worry about capturing changes during migration.&lt;/p&gt;
&lt;p&gt;The team decides to implement reverse sync for critical tables as a risk mitigation strategy - changes on the new database will flow back to the old system during a two-week validation period after cutover, allowing them to revert if issues arise. Batch jobs need to be accounted for separately in the rollback scenario. The team evaluates complete replay as well as capturing the changes as part of the Dsync reverse flow.&lt;/p&gt;
&lt;p&gt;Due to lack of documentation and numerous undocumented dependencies discovered in the codebase, this phase extends an additional 2-3 weeks beyond the original estimate.&lt;/p&gt;
&lt;h3 id=&quot;phase-2-environment-setup-and-tooling-preparation-1-3-weeks&quot;&gt;Phase 2: Environment Setup and Tooling Preparation (1-3 weeks)&lt;/h3&gt;
&lt;p&gt;The team provisions the target NoSQL cluster in their Cloud environment, configures Dsync with access to both source and target databases, and establishes monitoring and alerting.&lt;/p&gt;
&lt;p&gt;DNS issues with private links consume several days of troubleshooting. Security team reviews and permission grants take longer than expected, but by week 3 all infrastructure is operational.&lt;/p&gt;
&lt;h3 id=&quot;phase-3-code-changes-and-dev-testing-2-3-months&quot;&gt;Phase 3: Code Changes and Dev Testing (2-3 months)&lt;/h3&gt;
&lt;p&gt;This phase involves substantial parallel engineering effort across four streams:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Stream 1: Data Access Layer Refactoring&lt;/em&gt; - Engineers create a clean DAL interface abstracting all database operations. They systematically refactor the monolithic codebase to route all data access through this interface rather than making direct database calls. They then build a NoSQL implementation of the DAL. This work represents the largest engineering investment in the migration.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Stream 2: Batch Jobs and Pipeline Updates&lt;/em&gt; - The team updates nightly batch jobs and Databricks pipelines to work with the denormalized NoSQL schema. Several “surprises” emerge - aggregations that were simple SQL queries now require multiple steps, and some join patterns need complete rethinking.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Stream 3: Forward Data Migration and Transformation&lt;/em&gt; - Using Dsync in the dev environment, the team tests data migration and transformation logic repeatedly. They refine mappings, test performance, and optimize the target database configuration. Initial migrations take 6+ hours; after tuning they achieve 3-hour migration times in dev.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Stream 4: Reverse Sync Testing&lt;/em&gt; - The team configures and tests reverse transformations, ensuring changes made in the NoSQL database can flow back to the relational source. This provides confidence in their safety net strategy. Rollback of batch jobs is tested separately.&lt;/p&gt;
&lt;h3 id=&quot;phase-4-uat-testing-1-2-months&quot;&gt;Phase 4: UAT Testing (1-2 months)&lt;/h3&gt;
&lt;p&gt;UAT environment contains roughly half of production data volume (110GB). The team conducts extensive functional testing with business users, performance testing under realistic load, and capacity planning.&lt;/p&gt;
&lt;p&gt;They discover that their initial target database configuration is undersized for peak load and adjust accordingly. Batch jobs complete successfully, though some require optimization to meet their time windows.&lt;/p&gt;
&lt;p&gt;Several data model artifacts surface in UAT that weren’t present in dev’s smaller dataset -older records with different encoding, legacy status values no longer in use, and some foreign key relationships that exist in data but aren’t properly constrained. These findings drive updates to transformation logic.&lt;/p&gt;
&lt;h3 id=&quot;phase-5-production-dry-run-1-month-with-issues-extending-timeline-further&quot;&gt;Phase 5: Production Dry Run (1 month, with issues extending timeline further)&lt;/h3&gt;
&lt;p&gt;The team executes a complete migration using full production data (220GB) with Dsync’s CDC maintaining continuous sync. Application servers run against the migrated data in parallel with production traffic going to the old database.&lt;/p&gt;
&lt;p&gt;This reveals critical issues that didn’t appear in smaller environments. Old production records - some dating back 15+ years - contain data type inconsistencies and encoding problems that break transformation assumptions. In a handful of records, several fields that are expected to be dates contain text values. The target schema must be adjusted to handle these cases, which requires updating transformation logic, batch jobs, and the application DAL implementation. These changes propagate back through dev and UAT environments for validation.&lt;/p&gt;
&lt;p&gt;The dry run validates migration timing and infrastructure capacity -  actual production migration takes 4.5 hours, which is within acceptable bounds. It also reveals that one less-frequently-used API endpoint has 10x higher latency with the new database - investigation shows a missing index that was implicit in the relational schema.&lt;/p&gt;
&lt;p&gt;Issues discovered in the dry run extend this phase and push back the planned cutover date by two weeks.&lt;/p&gt;
&lt;h3 id=&quot;phase-6-cutover-preparation-1-2-weeks&quot;&gt;Phase 6: Cutover Preparation (1-2 weeks)&lt;/h3&gt;
&lt;p&gt;With all dry run issues resolved, the team builds a minute-by-minute cutover plan for a Saturday night/Sunday morning window. They assign specific responsibilities, prepare rollback procedures, and draft user communications. The plan includes checkpoints at 30-minute intervals with go/no-go decisions.&lt;/p&gt;
&lt;p&gt;Internal users receive two weeks’ notice, external users receive one week’s notice of the planned maintenance window. Customer support receives detailed talking points and FAQs.&lt;/p&gt;
&lt;h3 id=&quot;phase-7-production-migration-and-cutover-2-days&quot;&gt;Phase 7: Production Migration and Cutover (2 days)&lt;/h3&gt;
&lt;p&gt;Friday evening, the team begins final preparations. They check the health of all the services and endpoints, the source and the destination. No surprises.&lt;/p&gt;
&lt;p&gt;Saturday at 11pm, they initiate the migration following their detailed runbook:&lt;/p&gt;
&lt;p&gt;10.45pm - Final health-check before initiating the migration&lt;/p&gt;
&lt;p&gt;11:00pm - Enable read-only mode on the source database and pos&lt;/p&gt;
&lt;p&gt;11:05pm - Begin full data migration with Dsync&lt;/p&gt;
&lt;p&gt;3:20am - Data migration completes (4h 15m actual time)&lt;/p&gt;
&lt;p&gt;3:25am - Automated validation scripts run&lt;/p&gt;
&lt;p&gt;4:10am - Validation completes with complete match accounting for expected differences in concurrent data from batch jobs&lt;/p&gt;
&lt;p&gt;4:15am - Switch application configuration to new database and deploy new batch process&lt;/p&gt;
&lt;p&gt;4:30am - Smoke tests pass&lt;/p&gt;
&lt;p&gt;4.30am - GO/NO-GO Decision&lt;/p&gt;
&lt;p&gt;4:40am - Enable reverse sync from NoSQL to RDBMS (safety measure)&lt;/p&gt;
&lt;p&gt;4:45am - Begin gradual traffic ramp-up&lt;/p&gt;
&lt;p&gt;6:00am - Full traffic on new database&lt;/p&gt;
&lt;p&gt;8:00am - Business users begin validation&lt;/p&gt;
&lt;p&gt;Monday morning passes smoothly with banking hours traffic. By Monday evening, the migration is declared successful. Next Saturday afternoon, after a week of operation, the team disables reverse sync and formally decommissions the legacy system.&lt;/p&gt;
&lt;h3 id=&quot;phase-8-post-migration-monitoring-and-optimization-1-month&quot;&gt;Phase 8: Post-Migration Monitoring and Optimization (1 month)&lt;/h3&gt;
&lt;p&gt;During the first week, monitoring reveals one forgotten index needed by a weekly report job - easily remedied. The team makes several configuration optimizations based on production query patterns. By week four, all performance metrics meet or exceed targets, and the team transitions to normal operational monitoring.&lt;/p&gt;
&lt;h3 id=&quot;timeline-summary&quot;&gt;Timeline Summary:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Planning and Design: 6-7 weeks (2-4 weeks initially planned)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Environment Setup: 3 weeks&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Code Changes and Dev Testing: 3 months&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;UAT Testing: 1 month&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Production Dry Run: 1.5 months (1 month initially planned, extended due to issues)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Cutover Prep: 2 weeks&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Cutover Execution: 2 days&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Post-Migration: 1 month active monitoring and optimization&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Total: Approximately 8 months from kickoff to completion&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;10-lessons-learned-and-conclusion&quot;&gt;10. Lessons Learned and Conclusion&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Biggest Bottlenecks&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Migration tooling&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Code changes&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Overhead of communication and scheduling&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Even with a tool like Dsync and minimum required code changes, it’s not uncommon for migration timelines to extend when coordination between multiple teams is needed. In most cases it can’t be helped, but it pays off to be realistic in planning the budget and setting expectations with broader stakeholders.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Common Pitfalls to Avoid&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Underestimating the time required for dependency discovery and stakeholder alignment - add buffer to early phases&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Assuming test data represents production reality - data quality issues lurk in old records&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Skipping the production dry run to save time - this is where the most expensive issues are caught&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Inadequate monitoring and alerting - you can’t fix what you can’t see&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Poor communication with stakeholders - silence creates anxiety and distrust&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Success Factors&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Executive sponsorship and clear prioritization ensure teams can focus on migration work without competing demands&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Comprehensive testing at each phase catches issues when they’re cheaper to fix&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Realistic timeline estimates with built-in buffer accommodate inevitable surprises&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Strong collaboration between engineering, operations, and business teams keeps everyone aligned&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The right tools for the job - whether vendor solutions like Dsync or custom scripts -dramatically affect success probability.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Next Steps and Resources&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If you’re planning a database migration, start with thorough assessment. Understand your requirements, constraints, and risk tolerance. Engage stakeholders early. Consider proof-of-concept migrations with subsets of data to validate your approach.&lt;/p&gt;
&lt;p&gt;For complex migrations, especially RDBMS to NoSQL transformations, specialized tools can significantly reduce risk and timeline. &lt;a href=&quot;https://github.com/adiom-data/dsync/&quot;&gt;Adiom’s Dsync&lt;/a&gt;, for example, was purpose-built for these challenging scenarios.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How Dsync Helps&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Dsync addresses many of the pain points in database migrations through seamless integration between initial data copy and real-time CDC, resumability, observability, sophisticated transformation capabilities that handle the complexity of relational to NoSQL mapping, embedded validation tools that automate data integrity verification, and expert support from teams who’ve executed hundreds of migrations.&lt;/p&gt;
&lt;p&gt;For migrations where data transformation is required, downtime is unacceptable, and data integrity is critical - exactly the scenarios where in-house solutions fall short - specialized tools like Dsync transform a months-long, high-risk project into a manageable, well-supported process.&lt;/p&gt;
&lt;p&gt;Database migration is challenging, but with careful planning, the right tools, and realistic expectations, it’s an achievable goal that unlocks new capabilities for your applications and business. &lt;a href=&quot;https://www.adiom.io/contact&quot;&gt;Contact us&lt;/a&gt; for help with production migrations.&lt;/p&gt;
&lt;p&gt;You can download and try Dsync for your migration &lt;a href=&quot;https://github.com/adiom-data/dsync/&quot;&gt;on GitHub&lt;/a&gt;. We built it to make your migration experience seamless.&lt;/p&gt;
</content:encoded><category>strategy</category><category>sql</category><category>replication</category><author>Alexander Komyagin</author></item><item><title>[Part 4] Production Database Migration or Modernization: A Comprehensive Planning Guide</title><link>https://www.adiom.io/post/part-4-production-database-migration-or-modernization-a-comprehensive-planning-guide/</link><guid isPermaLink="true">https://www.adiom.io/post/part-4-production-database-migration-or-modernization-a-comprehensive-planning-guide/</guid><description>If you haven&apos;t read the first three parts, read them here:Part 1 - Migration Readiness and Key Factors Influencing Timeline and RiskPart 2 - Downtime Strategy Options and Migration ToolsPart 3 - Migration Planning and Post-Migration Validation Strategy7.</description><pubDate>Mon, 09 Feb 2026 05:05:31 GMT</pubDate><content:encoded>&lt;p&gt;The fourth part of our multi-post guide discusses common complications in production migrations as well as general best practices to ensure success of your project.&lt;/p&gt;
&lt;p&gt;If you haven’t read the first three parts, read them here:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.adiom.io/post/production-database-migration-or-modernization-a-comprehensive-planning-guide&quot;&gt;Part 1 - Migration Readiness and Key Factors Influencing Timeline and Risk&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.adiom.io/post/part-2-production-database-migration-or-modernization-a-comprehensive-planning-guide&quot;&gt;Part 2 - Downtime Strategy Options and Migration Tools&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.adiom.io/post/part-3-production-database-migration-or-modernization-a-comprehensive-planning-guide&quot;&gt;Part 3 -&lt;/a&gt; &lt;a href=&quot;https://www.adiom.io/post/part-3-production-database-migration-or-modernization-a-comprehensive-planning-guide&quot;&gt;Migration Planning and Post-Migration Validation Strategy&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;7-common-complications-and-mitigation&quot;&gt;7. Common Complications and Mitigation&lt;/h2&gt;
&lt;p&gt;Expect the unexpected. These complications appear in nearly every migration.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Legacy Code Dependencies and Technical Debt&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Codebases evolve over years, accumulating assumptions about database behavior. Stored procedures that seemed convenient become migration blockers. Undocumented business logic embedded in database triggers must be reimplemented. Tackle technical debt incrementally during the dev phase rather than attempting a big-bang refactor.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Lack of Code Documentation and Dependencies&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The engineer who wrote critical data access code left years ago. Documentation is sparse or outdated. Untangling dependencies becomes archaeological work. Budget extra time for discovery and invest in documenting what you learn. For complex environments, try to execute a production dry-run as early as possible - that’s where you’ll learn the most.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Database or Network Issues During Ingestion&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Network partitions, connection timeouts, and resource exhaustion can interrupt migration. Design for resilience and choose tools with retry logic, checkpointing to resume from failure points, rate limiting to avoid overwhelming source or target, and monitoring to detect issues quickly.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Tool Permissions and Access Control&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Migration tools need appropriate permissions on both source and target databases. In enterprise environments, obtaining these permissions through security review processes can take weeks. Address access requirements early.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Data Model Incompatibilities and Transformations&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Migrating from relational to NoSQL requires fundamental thinking shifts. Joins become embedded documents or separate queries. Transactions have different semantics. Carefully design your target schema and test transformations thoroughly with realistic data. When performing a dry run, test all the critical workflows to ensure that queries are executed efficiently.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Integration Dependencies&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Your database isn’t isolated. Data pipelines, reporting systems, third-party integrations, and internal tools all depend on database structure and availability. Catalog all dependencies early and coordinate changes across teams.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Performance Degradation During Migration&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Migration processes can saturate network bandwidth, max out CPU on source or target databases, and impact production workloads. Rate-limit your migration, schedule intensive operations during low-traffic periods, and monitor impact continuously.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Unexpected Data Quality Issues&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Old databases accumulate data quality problems: inconsistent formats, orphaned records, violated constraints that aren’t enforced, and edge cases in data types. These issues commonly surface during production dry runs when you encounter the full diversity of production data. Build data filtering and transformation logic to handle these scenarios.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;DNS&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If nothing else, it’s almost certain that DNS issues will haunt you in your production environment during the migration. Rehearse and test all the related changes ahead of time.&lt;/p&gt;
&lt;h2 id=&quot;8-best-practices&quot;&gt;8. Best Practices&lt;/h2&gt;
&lt;p&gt;Learn from our decade-long experience as well as the collective experience of the industry.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Comprehensive Testing in Non-Production Environments&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Test everything, repeatedly, in environments that mirror production. Automate tests so they can run frequently without manual effort. Include not just happy paths but failure scenarios and edge cases.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Incremental Migration When Possible&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Reduce risk by breaking large migrations into smaller chunks. Migrate less critical data or services first to refine your process. Each successful increment builds team confidence and improves procedures.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Complete Production Dry-runs&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;There’s nothing closer to your production than… your production. Do a dry-run, or two. A dry-run is a complete execution of your migration, including application re-deployment, &lt;em&gt;but without the cut over&lt;/em&gt;. &lt;strong&gt;Don’t skip steps.&lt;/strong&gt; Turn this into a well-planned and rehearsed activity, to avoid rollercoasters on the day of.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Automated Validation Scripts&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Manual data comparison doesn’t scale. Choose tools or build robust automation that can validate millions of records quickly and accurately. These scripts become invaluable assets for future migrations and ongoing data quality monitoring.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Clear Rollback Procedures&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Hope for the best, plan for the worst. Everyone involved should understand exactly what triggers a rollback and what steps to execute. Practice rollback procedures during dry runs.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Documentation and Runbooks&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Document your architecture, data transformations, migration procedures, and operational playbooks. Document the step-by-step project plan. This documentation helps during the migration and becomes institutional knowledge for operating the new system.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Post-Migration Performance Tuning&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Your initial migration focuses on correctness. After cutover, optimize based on real production query patterns. Add indexes, adjust configurations, and refine your data model based on actual performance metrics.&lt;/p&gt;
&lt;p&gt;In our next and the last post in this series we will showcase a sample project plan and will discuss the key lessons.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.adiom.io/contact&quot;&gt;Contact us&lt;/a&gt; for help with production migrations.&lt;/p&gt;
&lt;p&gt;Download and try Dsync for your migration &lt;a href=&quot;https://github.com/adiom-data/dsync/&quot;&gt;on GitHub&lt;/a&gt;. We built it to make your migration experience seamless.&lt;/p&gt;
</content:encoded><category>strategy</category><author>Alexander Komyagin</author></item><item><title>[Part 3] Production Database Migration or Modernization: A Comprehensive Planning Guide</title><link>https://www.adiom.io/post/part-3-production-database-migration-or-modernization-a-comprehensive-planning-guide/</link><guid isPermaLink="true">https://www.adiom.io/post/part-3-production-database-migration-or-modernization-a-comprehensive-planning-guide/</guid><description>In this third part of our multi-post guide we will discuss migration planning and post-migration validation strategy.</description><pubDate>Wed, 04 Feb 2026 15:53:49 GMT</pubDate><content:encoded>&lt;p&gt;In this third part of our multi-post guide we will discuss migration planning and post-migration validation strategy. It might even be the most important post in the series!&lt;/p&gt;
&lt;p&gt;If you haven’t read the first two parts, read them here:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.adiom.io/post/production-database-migration-or-modernization-a-comprehensive-planning-guide&quot;&gt;Part 1 - Migration Readiness and Key Factors Influencing Timeline and Risk&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.adiom.io/post/part-2-production-database-migration-or-modernization-a-comprehensive-planning-guide&quot;&gt;Part 2 - Downtime Strategy Options and Migration Tools&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;“Plan for what is difficult while it is easy, do what is great while it is small”, Sun Tzu&lt;/p&gt;
&lt;h2 id=&quot;5-migration-plan-and-timeline&quot;&gt;5. Migration Plan and Timeline&lt;/h2&gt;
&lt;p&gt;A structured, phased approach minimizes risk and ensures that the right resources are involved. Use the phases given below as a common framework, and feel free to adapt it to your unique environment as needed.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Phase 1: Planning and Design&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Develop comprehensive architecture diagrams showing data flows, define detailed input schema and schema mappings including all transformations, create a migration runbook documenting every step, identify dependencies across systems, and establish rollback criteria and procedures. Review business constraints, choose your migration strategy and tooling. Do a small POC if necessary.&lt;/p&gt;
&lt;p&gt;This phase typically takes 2-4 weeks but can extend significantly with complex stakeholder landscapes, architectural review boards, and infrastructure constraints.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Phase 2: Environment Setup and Tooling Preparation&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Provision target database infrastructure with appropriate capacity, configure migration tools and establish connectivity, set up monitoring and alerting for both source and target, ensure availability of non-production environments mirroring production, and implement security controls and access policies.&lt;/p&gt;
&lt;p&gt;Expect 1-3 weeks, with network configuration - private links, DNS, firewall rules - often being the source of unexpected delays.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Phase 3: Dev Testing&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This critical phase typically runs 2-3 months with parallel work streams:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Stream 1: Code Changes&lt;/em&gt; - Create or refactor your data access layer (DAL) to abstract database interactions. Rewrite application code to use the new interface and implement the DAL for your target database. This stream represents the bulk of engineering effort.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Stream 2: Integration and Batch Job Changes&lt;/em&gt; - Update all batch jobs, ETL processes, and data pipelines to work with the new schema and database paradigm. Surprises often emerge here as dormant edge cases surface. Often batch jobs lack test coverage. This is a perfect opportunity to fix that.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Stream 3: Data Migration Testing&lt;/em&gt; - Test your migration process repeatedly in dev environments. Test both initial data copy and change-data-capture (CDC). Validate forward transformations that reshape data for the new model. Iterate on performance tuning for both migration speed and target database configuration. The goal is to know how fast you &lt;em&gt;could&lt;/em&gt; go (and what that would require), and how fast you &lt;em&gt;need&lt;/em&gt; to go in order for the migration to be successful.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Stream 4: Reverse Sync Testing&lt;/em&gt; - If your strategy includes reverse sync as a safety measure (writing changes from the new database back to the old), test these reverse transformations thoroughly.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Phase 4: UAT Testing&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;With a UAT environment approximating production size (often 30-50% of production data), spend 1-2 months conducting comprehensive functional testing, performance testing under realistic load, capacity planning for the target database, and migration timing validation.&lt;/p&gt;
&lt;p&gt;UAT often reveals data model artifacts that weren’t present in smaller dev datasets. Test data that’s obsolete or doesn’t reflect current usage patterns can create misleading results, so work with real or recently sanitized production data when possible.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Phase 5: Production Dry Run&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This crucial phase - often 3-4 weeks or longer - involves executing &lt;em&gt;the full migration&lt;/em&gt; against production data without cutting over traffic. &lt;strong&gt;&lt;em&gt;Go all the way&lt;/em&gt;&lt;/strong&gt;, and run your application and batch jobs against the migrated data to validate correctness. Conduct complete integration testing with all dependent systems.&lt;/p&gt;
&lt;p&gt;Perform extensive data validation comparing source and target. Measure impact on the source database during migration, migration speed and bottlenecks, and target database performance under production query patterns.&lt;/p&gt;
&lt;p&gt;For high-risk migrations, consider an extended dry run where the target remains continuously in sync with the source for weeks or months while you compare API responses between systems to build confidence.&lt;/p&gt;
&lt;p&gt;Production data often contains artifacts from old records, inconsistent data types, and edge cases that never appeared in testing. Discovering these issues in the dry run is expensive - requiring changes to propagate back through dev and UAT - but far better than finding them during the actual cutover.&lt;/p&gt;
&lt;p&gt;Ensure to document all the steps, their timings and performance observations. Map out various edge cases (e.g. the destination or the source become unavailable for a short period of time, migration tool is interrupted, etc), test them and their impact on the process. For example, if your migration tooling or process isn’t resumable, requires downtime, and fails toward the end of your downtime window, you may as well call it. &lt;strong&gt;Don’t just test the happy path only&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Phase 6: Cutover Preparation&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Based on dry run learnings, build a detailed cutover plan specifying &lt;em&gt;every action down to the minute.&lt;/em&gt; Allocate resources ensuring the right people are available during the cutover window. Be wary of holidays and other high-risk periods. Pick the quietest time possible based on traffic patterns. Prepare user notifications for internal and external stakeholders.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note from experience: when final cutover steps are dependent on DNS updates, it’s best to rehearse that in advance.&lt;/em&gt; &lt;a href=&quot;https://adrianco.medium.com/the-internet-is-down-it-was-dns-again-e86341db21d5&quot;&gt;&lt;em&gt;DNS updates bring the Internet down.&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This phase typically requires 1-2 weeks. For complex migrations it’s prudent to prepare a backup cutover window.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Phase 7: Production Migration and Cutover&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;When everything is properly planned, the actual cutover is often anticlimactic - a 2-day window (or even less) of executing well-rehearsed steps. Continuous communication and pre-defined escalation paths ensure the team can respond quickly to any unexpected issues.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Phase 8: Post-Migration Monitoring and Optimization&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;For at least a month after cutover, maintain heightened monitoring. Watch for performance degradation, data inconsistencies, unexpected errors, and capacity issues. Commonly forgotten items - like indexes needed by infrequent batch jobs or new application endpoints - often surface during this period. Continue optimization based on real production traffic patterns.&lt;/p&gt;
&lt;h2 id=&quot;6-validation-strategy&quot;&gt;6. Validation Strategy&lt;/h2&gt;
&lt;p&gt;Data integrity is paramount. Your validation strategy should include multiple layers of verification.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Data Integrity Checks&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Implement automated validation scripts that compare row counts across tables, calculate and compare checksums for data blocks, sample random records for detailed field-by-field comparison, and validate referential integrity and constraints. Run these checks repeatedly - after initial migration in Dev and UAT, during the dry run, and again after cutover.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Application Testing&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Beyond data validation, verify that your application functions correctly: functional testing of all critical user journeys, performance testing to ensure response times meet SLAs, integration testing with all dependent systems, and end-to-end testing of business workflows. Automated test suites accelerate this process and provide regression protection.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Rollback Procedures and Criteria&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Define clear criteria for success or rollback: What data inconsistency rate is acceptable? What level of performance degradation triggers rollback? How long can resolution take before you must roll back?&lt;/p&gt;
&lt;p&gt;Document and rehearse rollback procedures. In a dual-write scenario, rollback might mean redirecting read traffic back to the old database. For migrations with downtime, you may need to rely on reverse sync. Without reverse sync, you would need to accept a certain loss if you go back.&lt;/p&gt;
&lt;p&gt;From 100’s of migrations that we’ve been involved in, we only saw a handful where a rollback was actually triggered - if all previous steps were properly followed, the rollback scenario is merely a theoretical possibility. However, if the conditions for it are not well defined, it can add very real stress during the critical cutover time window.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Monitoring and Alerting Setup&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Establish comprehensive monitoring before cutover including database performance metrics, application error rates, API latency percentiles, data consistency checks, and business metrics like transaction volumes. Configure alerts with appropriate thresholds to catch issues quickly.&lt;/p&gt;
&lt;p&gt;Configure monitoring for migration tooling - you should have full visibility into its progress, ETA for completion, and any errors.&lt;/p&gt;
&lt;p&gt;In our next post in this series we will discuss common complications that affect even the best planned migrations, and migration best practices.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.adiom.io/contact&quot;&gt;Contact us&lt;/a&gt; for help with production migrations.&lt;/p&gt;
&lt;p&gt;Download and try Dsync for your migration &lt;a href=&quot;https://github.com/adiom-data/dsync/&quot;&gt;on GitHub&lt;/a&gt;. We built it to make your migration experience seamless.&lt;/p&gt;
</content:encoded><category>strategy</category><category>replication</category><author>Alexander Komyagin</author></item><item><title>[Part 2] Production Database Migration or Modernization: A Comprehensive Planning Guide</title><link>https://www.adiom.io/post/part-2-production-database-migration-or-modernization-a-comprehensive-planning-guide/</link><guid isPermaLink="true">https://www.adiom.io/post/part-2-production-database-migration-or-modernization-a-comprehensive-planning-guide/</guid><description>Migration performance and risks need to be carefully balanced through proper downtime strategy and optimal tool selection3.</description><pubDate>Sat, 31 Jan 2026 03:31:29 GMT</pubDate><content:encoded>&lt;p&gt;This is a second part of our multi-post guide that walks through the essential components of planning and executing a successful production database migration for large-scale backend services.&lt;/p&gt;
&lt;p&gt;If you haven’t read the first part, where we cover Migration Readiness Assessment and the Six Key Factors Influencing Timeline and Risk, you can find it &lt;a href=&quot;https://www.adiom.io/post/production-database-migration-or-modernization-a-comprehensive-planning-guide&quot;&gt;in Part 1&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Migration performance and risks need to be carefully balanced through proper downtime strategy and optimal tool selection&lt;/p&gt;
&lt;h2 id=&quot;3-downtime-strategy-options&quot;&gt;3. Downtime Strategy Options&lt;/h2&gt;
&lt;p&gt;Your downtime strategy fundamentally shapes your migration approach and timeline.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Some Downtime (Planned Maintenance Window)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This traditional approach involves scheduling a maintenance window - typically several hours to a full day - during which services are completely or partially unavailable (e.g. read-only mode) while you migrate data and cut over to the new database.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Pros:&lt;/em&gt; Simplest to implement, lowest risk of data inconsistencies, easier validation, straightforward rollback if issues arise.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Cons:&lt;/em&gt; Service interruption impacts users, requires careful timing and communication, may not be acceptable for globally distributed services.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Timeline:&lt;/em&gt; Shortest overall project timeline but concentrated downtime during cutover.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Best for:&lt;/em&gt; Applications with natural low-traffic periods or off-hours (e.g. insurance, banking), internal tools, or when business requirements permit scheduled maintenance.&lt;/p&gt;
&lt;p&gt;For large databases or network-constrained environments, it’s important to ensure that the migration window covers at least 1.5-2x actual data migration time to account for variability in data ingestion and minor deviations from the original plan, such as transient network or database issues.&lt;/p&gt;
&lt;p&gt;Although most companies immediately discount this old-school approach because they expect the downtime period to be long, &lt;em&gt;many modern databases coupled with highly-parallelized and scalable migration tooling can easily make migrating many TBs and Billions of records a matter of hours rather than days.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Minimal Downtime (Quick Cutover)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Migrate the bulk of data, continuously sync the deltas (starting from the point in time right before the initial data copy to avoid losing data), then execute a brief cutover window (minutes to an hour) to sync final changes and switch traffic to the new database.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Pros:&lt;/em&gt; Significantly reduced user impact, most data migrated without affecting production, maintains business continuity.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Cons:&lt;/em&gt; Requires CDC or careful change tracking, more complex orchestration, higher stakes during cutover window.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Timeline:&lt;/em&gt; Medium complexity; bulk migration can happen over days or even weeks while services run normally.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Best for:&lt;/em&gt; Services that can only tolerate brief interruptions during low-traffic periods.&lt;/p&gt;
&lt;p&gt;It’s worth noting that blending CDC (change-data-capture) and initial data copy requires two distinct data processing paths for the migration. &lt;em&gt;They need to be well coordinated and individually tested from the data integrity and performance perspectives.&lt;/em&gt; The CDC mechanism should be fast enough to catch up with all the changes within a reasonable and predictable timeframe, and continue replicating them in near-real-time. The initial data copy should be fast enough to reduce the catch up period and give the CDC part the best odds to succeed.&lt;/p&gt;
&lt;p&gt;Some modern database migration tools implement the above already, but the burden of proper testing and evaluation always falls on the end user.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Zero Downtime (Dual Writes, Gradual Migration)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Implement dual writes via a dedicated DAL (Database Abstraction Layer) where all changes go to both old and new databases simultaneously, then gradually shift read traffic to the new database after validating data consistency. The bulk of data is backfilled in the background via a separate process.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Pros:&lt;/em&gt; No user-facing downtime, extensive validation possible before cutover, gradual rollout reduces risk.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Cons:&lt;/em&gt; Most complex implementation requiring significant code changes, increased operational complexity and monitoring during transition, potential for data inconsistencies between systems, extended timeline with both systems running in parallel.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Timeline:&lt;/em&gt; Longest overall timeline but eliminates concentrated downtime.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Best for:&lt;/em&gt; Mission-critical services where any downtime is unacceptable, services with global user bases across time zones.&lt;/p&gt;
&lt;p&gt;Key challenges specific to this approach:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Consistency:&lt;/strong&gt; Dual writes can cause data drift between the source and the destination unless each write has a transactional semantic and the writes order is strictly maintained for each record across both systems. Even if the business side is ok with &lt;em&gt;some&lt;/em&gt; drift, no guarantees can be made here - the only practical approach is testing and measuring the drift.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Race Conditions:&lt;/strong&gt; Unless the write workload is insert-only, the abstraction layer needs logic to prevent backfills from overwriting fresh data, and the destination write path should be able to handle possible conflicts.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Data Anomalies:&lt;/strong&gt; Production data often has “surprises” that only show up after the move unless the application code has been tested with the post-migration data - this is best done as part of the production dry-run.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Migration in Batches&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;For complex systems, consider migrating in phases (“blue-green” approach) rather than all at once.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Multi-tenant Systems:&lt;/em&gt; Group tenants logically (by size, activity level, or business relationship) and migrate each group separately. This requires specialized middleware and feature flags to route requests to the appropriate database based on the tenant. Starting with smaller, lower-risk tenants allows you to refine your process before migrating larger customers.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Multi-service Systems:&lt;/em&gt; In a microservices architecture, identify independent groups of services and migrate them separately. Services with fewer dependencies make ideal starting points. This incremental approach reduces blast radius and allows learning from each migration.&lt;/p&gt;
&lt;p&gt;A variation of this approach is to split the migration by logically separate and independent groups of schemas/tables/collections.&lt;/p&gt;
&lt;h2 id=&quot;4-migration-approaches-and-tools&quot;&gt;4. Migration Approaches and Tools&lt;/h2&gt;
&lt;p&gt;Selecting the right tooling is critical for success as tools underpin the execution of any of the chosen approaches.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Vendor-Provided Tools&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Cloud providers and database vendors often offer native migration services: MongoDB Atlas Migrations, AWS Database Migration Services from Azure, AWS and Google.&lt;/p&gt;
&lt;p&gt;These tools integrate seamlessly with their respective cloud ecosystems and support a range of source and target database combinations.&lt;/p&gt;
&lt;p&gt;Vendors like MongoDB offer specialized tooling like mongosync and MongoDB’s Relational Migrator.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Pros:&lt;/em&gt; Easy to set up, vendor support.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Cons:&lt;/em&gt; The tools have very limited scope and only cater to the lowest 50th percentile of workloads. Most of them are SaaS-based and move data over the public internet.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Best for:&lt;/em&gt; Workloads of average or below-average size and complexity, with little or no special requirements.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Specialized Third-Party Solutions&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Tools like Adiom’s Dsync, Oracle’s Golden Gate and Fivetran provide advanced capabilities for complex migrations. Dsync, for example, excels at NoSQL and RDBMS to NoSQL migrations with sophisticated transformation capabilities, modular extensions, and real-time CDC for minimal downtime.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Pros:&lt;/em&gt; Optimized tooling for repeatable and scalable execution of migrations with minimum or no-downtime. Easy to operationalize. Specialized expertise and support.&lt;/p&gt;
&lt;p&gt;Cons: Your company needs to onboard another vendor unless the solution is available in Open Source or the tool provider has a partnership with the destination database vendor.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Best for:&lt;/em&gt; Large-scale and mission-critical migrations. Complex transformations (especially RDBMS to NoSQL). Scenarios where specialized support and expertise add significant value.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Custom Scripts and Open-Source Tools&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Apache Spark for data processing, Debezium for CDC from various databases, Kafka Connect for streaming data pipelines, and custom ETL scripts give you maximum flexibility. Modern AI-tools like Copilot and Claude Code can help you to quickly create data migration scripts.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Pros:&lt;/em&gt; Full control of the process with no overhead of working with vendors.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Cons:&lt;/em&gt; Limited observability and scalability. Reliability and resumability are hard to implement without dedicated design reviews and testing.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Best for:&lt;/em&gt; Straightforward one-way migrations for small datasets (10’s of GBs). Can be used for larger and more complex migrations when your company has the necessary expertise and can allocate resources to the project.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Selection Criteria&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Choose tools based on your source and target database types, data volume and transformation complexity, downtime tolerance, team expertise, budget, and whether you need ongoing support. In many cases, a hybrid approach combining vendor tools or scripts for smaller or less-critical databases or schemas along with specialized tooling for large critical ones yields the best results.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;At Adiom, our goal is to give customers the best of both worlds. We offer specialized database migration solution&lt;/em&gt; &lt;a href=&quot;https://docs.adiom.io/&quot;&gt;&lt;em&gt;Dsync&lt;/em&gt;&lt;/a&gt; &lt;em&gt;and we closely partner with database vendors like Microsoft and MongoDB to reduce friction and risk, and to accelerate timelines for workload migrations.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In our next post in this series we will discuss migration planning, timelines and common complications.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.adiom.io/contact&quot;&gt;Contact us&lt;/a&gt; for help with production migrations.&lt;/p&gt;
&lt;p&gt;Download and try Dsync for your migration &lt;a href=&quot;https://github.com/adiom-data/dsync/&quot;&gt;on GitHub&lt;/a&gt;. We built it to make your migration experience seamless.&lt;/p&gt;
</content:encoded><category>strategy</category><category>replication</category><author>Alexander Komyagin</author></item><item><title>[Part 1] Production Database Migration or Modernization: A Comprehensive Planning Guide</title><link>https://www.adiom.io/post/production-database-migration-or-modernization-a-comprehensive-planning-guide/</link><guid isPermaLink="true">https://www.adiom.io/post/production-database-migration-or-modernization-a-comprehensive-planning-guide/</guid><description>Migrating a production database supporting critical backend API services is one of the most challenging undertakings in software engineering.</description><pubDate>Mon, 26 Jan 2026 05:00:28 GMT</pubDate><content:encoded>&lt;p&gt;Migrating a production database supporting critical backend API services is one of the most challenging undertakings in software engineering. Whether you’re modernizing from a legacy relational database to a NoSQL database like MongoDB, moving to a cloud-native solution like Azure Cosmos DB or AWS DynamoDB, or simply upgrading your database to a newer version, the stakes are high. A poorly executed migration at its worst can result in data loss, extended downtime, revenue impact, and erosion of customer trust. Not even mentioning frustration of internal stakeholders!&lt;/p&gt;
&lt;p&gt;Database migrations are often a nail-biter - but they don’t have to be.&lt;/p&gt;
&lt;p&gt;Commonly, migration timelines extend 4-6x longer than originally anticipated due to poor preparation, planning and internal coordination. This extension drives up not only costs, but also uncertainty and risks associated with other projects that are impacted by the migration.&lt;/p&gt;
&lt;p&gt;This multi-post guide walks through the essential components of planning and executing a successful production database migration for large-scale backend services.&lt;/p&gt;
&lt;h2 id=&quot;1-migration-requirements--assessment&quot;&gt;1. Migration Requirements &amp;amp; Assessment&lt;/h2&gt;
&lt;p&gt;Before diving into technical implementation, establish a clear foundation for your migration project.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Business Requirements and Success Criteria&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Define what success looks like. Are you migrating to reduce costs, improve performance, enable new features, or meet compliance requirements? Establish measurable criteria such as maximum acceptable downtime, target performance metrics, data integrity requirements, and budget constraints. These objectives will guide every subsequent decision.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Current Database Assessment&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Conduct a thorough analysis of your existing database including total data volume, number of tables and relationships, read and write query patterns and hotspots, current performance baselines, backup and recovery procedures, and existing monitoring and alerting. Understanding your starting point is critical for accurate planning.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Target Database Selection and Justification&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Choose your target database based on your specific requirements rather than trends. Consider factors like workload characteristics (OLTP vs. OLAP), scalability requirements, consistency vs. availability tradeoffs, operational complexity, team expertise, and total cost of ownership. Document your rationale for stakeholder buy-in.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Codebase Assessment&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Analyze how your application interacts with the database, including the code embedded server-side in the database in the form of stored procedures and triggers. Map your data models, access patterns, and API endpoints. Identify which endpoints are read-heavy versus write-heavy, which queries are most complex, and where performance bottlenecks exist. Understanding the coupling between your application and database will reveal the scope of code changes required.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Integrations and Batch Jobs&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Review and document integration with other systems, data pipelines and other in-flows and out-flows. Map the workflows, workload types, and dependencies on the data model.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Infrastructure and Networking&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Carefully review the infrastructure required for the migration: available headroom on the source database, possible bottlenecks on the network path between the source and the destination, as well as the type of the connection that will be used (Public IP/VPN/PrivateLink). Additionally, investigate elasticity in the destination database to accommodate the large ingestion job for initial data copy. Ideally, it can be temporarily upscaled.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Stakeholder Alignment and Communication Plan&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Database migrations affect multiple teams. Identify all the relevant stakeholders and establish a communication plan that keeps engineering teams, DevOps, product management, customer support, and executive leadership informed throughout the process. Regular updates on progress, risks, and timeline changes are essential for maintaining alignment.&lt;/p&gt;
&lt;h2 id=&quot;2-six-key-factors-influencing-timeline-and-risk&quot;&gt;2. Six Key Factors Influencing Timeline and Risk&lt;/h2&gt;
&lt;p&gt;While many factors might affect a migration, we identified &lt;strong&gt;six&lt;/strong&gt; as the most critical impacting both the duration and risk profile of your migration.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. Data Volume and Complexity&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A 10GB database might migrate in less than an hour, while a multi-terabyte database could take weeks. Long data migration jobs increase risks exponentially, as they prolong your exposure and make testing and migration attempts more expensive. Data complexity - including data types and constraints - compounds the challenge beyond raw size, especially when moving to a different vendor where not all of them may be supported. Last but not least, large data sets often hide legacy records from an old application version or production testing. Those legacy records are sometimes malformed and cause unexpected problems during the production migration.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. Existing Abstraction Layers&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The presence and quality of your Object-Relational Mapping (ORM) layer or Data Access Layer (DAL) significantly affects migration difficulty. A well-designed abstraction layer allows you to swap database implementations with minimal application code changes. Conversely, SQL queries scattered throughout your codebase create a massive refactoring challenge.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. Change Data Capture Capabilities&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;CDC is crucial for minimizing downtime and enabling zero-downtime migrations. If your source database supports CDC, you can continuously replicate changes during the migration process. Without CDC, you’re limited to snapshot-based approaches that require longer downtime windows. Note that some databases don’t support native CDC capabilities at all (e.g. Cassandra) and some support multiple options (e.g. LogMiner or XStream in Oracle). It is possible to get CDC-like capabilities with Change Tracking - whether native like in SQL Server or via a special version or lastModified field in each record. Different CDC approaches have specific requirements like installing software on a database server, maintaining triggers, and they all offer different performance profiles. &lt;em&gt;It’s critical to establish that your CDC mechanism offers at least 2-3x your maximum data velocity.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4. Database Schema Complexity and Data Model Changes&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Migrating from a normalized relational model to a denormalized NoSQL model requires careful planning. Every join that previously happened in the database must be rethought. Consider how you’ll handle transactions, maintain data consistency, and model relationships in the new paradigm. Review required data transformations from the feasibility perspective, and analyze the changes required in side jobs.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;5. Application Architecture and Database Coupling&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Monolithic applications tightly coupled to their databases present greater challenges than microservices with clean separation of concerns. Assess how deeply database-specific features (stored procedures, triggers, custom types) are embedded in your architecture.&lt;/p&gt;
&lt;p&gt;Monolithic applications generally require longer testing cycles and more coordination for changes. Notably, if the code in a monolithic application isn’t frozen, it’s common for migration-related changes to pile-up behind active feature and bug-fix work.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;6. Data Migration Tooling&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Data migration is the core activity and the foundation for any database migration or modernization project. A solid foundation is built on tooling that enables repeatable, reliable, fast and predictable execution. For a small database, a simple script might suffice. But large and mission-critical databases require purpose-built and supported solutions, that have flexibility to accommodate your specific requirements.&lt;/p&gt;
&lt;p&gt;Look forward to the next post in the series! There we will discuss migration approaches and downtime strategies.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.adiom.io/contact&quot;&gt;Contact us&lt;/a&gt; for help with production migrations.&lt;/p&gt;
&lt;p&gt;Download and try Dsync for your migration &lt;a href=&quot;https://github.com/adiom-data/dsync/&quot;&gt;on GitHub&lt;/a&gt;. We built it to make your migration experience seamless.&lt;/p&gt;
</content:encoded><category>strategy</category><category>mongodb</category><category>cosmos-db</category><category>dynamodb</category><category>azure</category><category>aws</category><author>Alexander Komyagin</author></item><item><title>Cost-effective vector embeddings storage with AWS S3 Vectors</title><link>https://www.adiom.io/post/cost-effective-vector-embeddings-storage-with-aws-s3-vectors/</link><guid isPermaLink="true">https://www.adiom.io/post/cost-effective-vector-embeddings-storage-with-aws-s3-vectors/</guid><description>Vector pipeline (courtesy of Vercel)Ever since vector stores and databases took the database market by storm in 2023-24, we ended up with a plethora of specialized vector databases such as Pinecone, Weaviate, Milvus, Qdrant.</description><pubDate>Wed, 14 Jan 2026 17:16:35 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;Vector pipeline (courtesy of Vercel)&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2916&quot; height=&quot;1368&quot; src=&quot;/_astro/01.DQWGFXwo_IW4zO.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Vector pipeline (courtesy of &lt;a href=&quot;https://vercel.com/kb/guide/vector-databases&quot;&gt;Vercel&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;Ever since vector stores and databases took the database market by storm in 2023-24, we ended up with a plethora of specialized &lt;strong&gt;vector databases&lt;/strong&gt; such as Pinecone, Weaviate, Milvus, Qdrant. Many of OLTP databases quickly jumped on the train and added support for &lt;strong&gt;vector indexes&lt;/strong&gt; - notably MongoDB and PostgreSQL - but the actual embeddings are still stored along with other operational data, competing for CPU, RAM and storage resources.&lt;/p&gt;
&lt;p&gt;Since then it became apparent that the embeddings workload is significantly different from the regular OLTP. Vectors are stored en-masse, and most of them are accessed relatively infrequently or never at all. Storing that kind of data and &lt;strong&gt;serving it from your OLTP system is prohibitively expensive&lt;/strong&gt; - it’s not enough to just build a great vector index, but the cost/performance ratio has to be good.&lt;/p&gt;
&lt;p&gt;As the market is adapting, a new category of players and open formats has emerged - those based on object storage. &lt;a href=&quot;https://turbopuffer.com/&quot;&gt;Turbopuffer&lt;/a&gt;, &lt;a href=&quot;https://lancedb.com/&quot;&gt;LanceDB&lt;/a&gt;, and now native &lt;a href=&quot;https://aws.amazon.com/blogs/aws/introducing-amazon-s3-vectors-first-cloud-storage-with-native-vector-support-at-scale/&quot;&gt;S3 Vector Indexes&lt;/a&gt;. We’re especially excited about the latter, as it dramatically simplifies the operational stack, and we hope that it will live up to the expectations.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;S3 Vector bucket&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1830&quot; height=&quot;472&quot; src=&quot;/_astro/02.CxxpomHX_3myzy.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;S3 Vector bucket&lt;/p&gt;
&lt;p&gt;For users wanting to try it out and export their existing vectors away from pgVector and other solutions, &lt;a href=&quot;https://github.com/adiom-data/dsync/&quot;&gt;Dsync&lt;/a&gt; now supports S3 Vectors as a destination. The feature is currently in “Public Preview”. Please feel free to share your feedback, ideas, and requests for help via our &lt;a href=&quot;https://www.adiom.io/contact&quot;&gt;Contact Form&lt;/a&gt; or our &lt;a href=&quot;https://discord.gg/r4xzVfMQeU&quot;&gt;Discord Channel&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Dsync is the most effective and seamless solution for data mobility between different databases and data stores (check out the full list of supported connectors &lt;a href=&quot;https://docs.adiom.io/getting-started/what-is-supported&quot;&gt;in the Dsync docs&lt;/a&gt;!). To use Dsync to migrate your vectors &lt;strong&gt;from pgVector to S3 Vectors&lt;/strong&gt;, you need to create a new vector bucket and then a new vector index:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Creating a new S3 vector bucket&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1499&quot; height=&quot;355&quot; src=&quot;/_astro/03.CyEuhVz7_Z2pC0c4.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Creating a new S3 vector bucket&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Creating a new S3 vector index&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1494&quot; height=&quot;475&quot; src=&quot;/_astro/04.C-DsW2aj_2up6YX.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Creating a new S3 vector index&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Make sure to set the same number of dimensions as in your source embeddings.&lt;/strong&gt; In my test setup, I have 3-dimensional vectors in the “embedding” column of the “public.items” table:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;zsh% psql postgresql://XX:YY@localhost:5432&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;postgres=# select * from items;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; id | embedding&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;----+-----------&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  1 | [1,2,3]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  2 | [4,5,6]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;(2 rows)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once the vector index is set up, migrating the embeddings to your new S3 Vector Index with &lt;strong&gt;Dsync&lt;/strong&gt; is as easy as a single command, provided you already logged into AWS in your CLI via “aws sso login”, and downloaded and built Dsync from our &lt;a href=&quot;https://github.com/adiom-data/dsync/&quot;&gt;repo&lt;/a&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;./dsync&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --mode=InitialSync&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --ns&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;public.items:alex-s3vec-index&quot;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; postgresql://XX:YY@localhost:5432&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; s3vector&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --bucket=alex-s3vec-test&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --vector-key=embedding&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Lastly, the AWS S3 Vectors is still a new feature, so please take a minute to go over the&lt;/p&gt;
&lt;p&gt;limitations, especially the rate limits. The Dsync S3 Vectors connector supports “–rate-limit” and “–batch-size” options that you can adjust:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;./dsync&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --mode=InitialSync&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --ns&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;public.items:alex-s3vec-index&quot;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; postgresql://XX:YY@localhost:5432&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; s3vector&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --bucket=alex-s3vec-test&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --vector-key=embedding&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --rate-limit&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 3000&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --batch-size&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 500&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Dsync can also retrieve live changes from the source database and update S3 vectors in real-time via CDC, rather than just doing a one-time sync (skip the “–mode=InitialSync option”):&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;./dsync&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --ns&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;public.items:alex-s3vec-index&quot;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; postgresql://XX:YY@localhost:5432&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; s3vector&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --bucket=alex-s3vec-test&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --vector-key=embedding&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Happy migrating!&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.adiom.io&quot;&gt;Dsync Docs&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.adiom.io/contact&quot;&gt;Contact Form&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://discord.gg/r4xzVfMQeU&quot;&gt;Discord Channel&lt;/a&gt;&lt;/p&gt;
</content:encoded><category>engineering</category><category>mongodb</category><category>sql</category><category>vector</category><category>s3</category><category>replication</category><author>Alexander Komyagin</author></item><item><title>Announcing DocumentDB support: an Open Source MongoDB compatible Database</title><link>https://www.adiom.io/post/announcing-documentdb-support-an-open-source-mongodb-compatible-database/</link><guid isPermaLink="true">https://www.adiom.io/post/announcing-documentdb-support-an-open-source-mongodb-compatible-database/</guid><description>At Adiom, we firmly believe in the power of true Open Source Software to advance the ecosystem and enable unhindered innovation.</description><pubDate>Tue, 16 Dec 2025 04:55:03 GMT</pubDate><content:encoded>&lt;p&gt;At Adiom, we firmly believe in the power of true Open Source Software to advance the ecosystem and enable unhindered innovation. We’re excited to announce full Azure DocumentDB support as a source and as a destination, including the managed and the self-hosted versions.&lt;/p&gt;
&lt;p&gt;Azure DocumentDB is built on PostgreSQL and uses custom extensions for enabling MongoDB compatibility. It lacks certain features, namely Change Streams, and in general can be considered as lagging several versions behind MongoDB’s main branch, but with AWS and Microsoft &lt;a href=&quot;https://aws.amazon.com/blogs/opensource/aws-joins-the-documentdb-project-to-build-interoperable-open-source-document-database-technology/&quot;&gt;joining forces&lt;/a&gt; on this one, we believe that the gap will start shrinking quickly.&lt;/p&gt;
&lt;p&gt;While AWS already has a product with the same name that has MongoDB compatibility, Microsoft took a very different approach and invested in their solution becoming a contribution to OSS and Linux Foundation.&lt;/p&gt;
&lt;p&gt;If you want to replicate or migrate your database to DocumentDB from MongoDB or another database, the process is &lt;strong&gt;as seamless as a single command, whether you have 100 documents or 1 billion&lt;/strong&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;dsync&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; $SOURCE_URI $DOCUMENTDB_URI&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you want to see progress in your CLI rather than the Web version:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;dsync&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --progress&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --logfile&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; dsync.log&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; $SOURCE_URI $DOCUMENTDB_URI&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;More options and supported sources can be found in our &lt;a href=&quot;https://docs.adiom.io/&quot;&gt;documentation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Dsync takes care of parallelization, write batch optimization, reporting and automatically coordinating real-time CDC data capture with the initial data snapshot while maintaining data integrity. For large (&amp;gt;100GB) and mission-critical deployments, Dsync has a horizontally-scalable &lt;a href=&quot;https://github.com/adiom-data/public/tree/main&quot;&gt;Enterprise version&lt;/a&gt; that features resumability and OpenTelemetry-compatible observability.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note that for a MongoDB source to work with CDC, it needs to be a replica set or a sharded cluster. Otherwise you can pass the “–mode InitialSync” option to dsync to skip CDC.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Read more:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://documentdb.io/docs&quot;&gt;https://documentdb.io/docs&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=vdB7fZvQC-Y&quot;&gt;https://www.youtube.com/watch?v=vdB7fZvQC-Y&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Try dsync:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/adiom-data/dsync/&quot;&gt;https://github.com/adiom-data/dsync/&lt;/a&gt;&lt;/p&gt;
</content:encoded><category>product</category><category>mongodb</category><category>sql</category><category>documentdb</category><category>replication</category><category>azure</category><author>Alexander Komyagin</author></item><item><title>Introducing S3 Support in dsync: Lightning-Fast Direct Transfer</title><link>https://www.adiom.io/post/introducing-s3-support-in-dsync-lightning-fast-direct-transfer/</link><guid isPermaLink="true">https://www.adiom.io/post/introducing-s3-support-in-dsync-lightning-fast-direct-transfer/</guid><description>We&apos;re excited to announce that dsync now supports Amazon S3 as both a source and destination.</description><pubDate>Wed, 10 Dec 2025 00:26:50 GMT</pubDate><content:encoded>&lt;p&gt;We’re excited to announce that &lt;a href=&quot;https://github.com/adiom-data/dsync/&quot;&gt;&lt;strong&gt;dsync&lt;/strong&gt;&lt;/a&gt; now supports Amazon S3 as both a source and destination. This opens up powerful new possibilities for data migration workflows.&lt;/p&gt;
&lt;h2 id=&quot;what-this-means-for-you&quot;&gt;What This Means for You&lt;/h2&gt;
&lt;p&gt;With S3 support, you can now export data directly from any supported connector - including DynamoDB, Azure Cosmos DB, MongoDB, and PostgreSQL - straight to S3, or import it back just as easily. The process is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Direct&lt;/strong&gt;: No intermediate storage required&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Fast&lt;/strong&gt;: Fully parallelized operations&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Simple&lt;/strong&gt;: Clean, intuitive command structure&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Your data is stored in S3 as organized JSON arrays within .json files, using a namespace-based directory structure that’s both human-readable and machine-friendly.&lt;/p&gt;
&lt;h2 id=&quot;quick-example&quot;&gt;Quick Example&lt;/h2&gt;
&lt;p&gt;Exporting two DynamoDB tables to S3 is as simple as:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;./dsync&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --mode&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; InitialSync&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --namespace&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;table1,table2&quot;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; dynamodb&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; s3://test&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This creates the following structure in your s3://test bucket:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;table1/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;├── .metadata.json&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;├── xxxxxx.json&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;├── yyyyyy.json&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;└── ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;table2/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;├── .metadata.json&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;├── aaaaaa.json&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;├── bbbbbb.json&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;└── ...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The .metadata.json file tracks record counts in each JSON file, enabling progress reporting during imports and quick validation of your data.&lt;/p&gt;
&lt;h2 id=&quot;flexible-imports&quot;&gt;Flexible Imports&lt;/h2&gt;
&lt;p&gt;When importing from S3, dsync reads .json files from your specified path. The folder structure automatically maps to namespaces, even with nested directories. Best of all, imports work with &lt;em&gt;any&lt;/em&gt; valid JSON array files - not just those created by dsync.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;./dsync&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --mode&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; InitialSync&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; s3://test&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; dynamodb&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Want to validate your data without writing anywhere? Use the special /dev/null connector:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;./dsync&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --mode&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; InitialSync&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; s3://test&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; /dev/null&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --log-json&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;why-we-built-this&quot;&gt;Why We Built This&lt;/h2&gt;
&lt;p&gt;This feature emerged from a real need: we required a robust solution for retaining large volumes of data from our internal deployments. After evaluating existing S3 export/import tools, we found them universally inadequate. Common issues included:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Requiring local disk dumps as intermediaries&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Painfully slow performance&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Complex, brittle automation&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Whereas native DynamoDB export to S3 using AWS console took close to 9 hours, dsync took less than 10 minutes!&lt;/p&gt;
&lt;p&gt;We built the S3 dsync connector to solve these problems for ourselves, and we’re thrilled to share it with our customers and the community.&lt;/p&gt;
&lt;h2 id=&quot;fine-tuning-your-exports&quot;&gt;Fine-Tuning Your Exports&lt;/h2&gt;
&lt;p&gt;The S3 connector offers several options to customize behavior:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;./dsync&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --mode&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; InitialSync&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --namespace&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;table1,table2&quot;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; dynamodb&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; s3://test&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [options]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Available options:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;--pretty-json – Format output files for readability&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;--max-total-memory – Control memory usage (default: 100MB)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;--max-file-size – Set maximum file size in S3 (default: 10MB)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Prefer CLI progress output?&lt;/strong&gt; Add the –progress and –logfile flags:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;./dsync&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --progress&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --logfile&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; /tmp/dsync.log&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --mode&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; InitialSync&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  --namespace&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;table1,table2&quot;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; dynamodb&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; s3://test&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;learn-more&quot;&gt;Learn More&lt;/h2&gt;
&lt;p&gt;For complete documentation on dsync and its capabilities, visit our &lt;a href=&quot;https://claude.ai/chat/link&quot;&gt;documentation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Happy exporting-importing!&lt;/p&gt;
</content:encoded><category>product</category><category>mongodb</category><category>cosmos-db</category><category>dynamodb</category><category>sql</category><category>s3</category><author>Alexander Komyagin</author></item><item><title>Accelerating Migrations to Cosmos DB NoSQL: White Paper</title><link>https://www.adiom.io/post/accelerating-migrations-to-cosmos-db-nosql-white-paper/</link><guid isPermaLink="true">https://www.adiom.io/post/accelerating-migrations-to-cosmos-db-nosql-white-paper/</guid><description>Azure Cosmos DB for NoSQL is a general JSON database with a rich SQL-like interface, multi-region deployments (including multi-region writes), and strong availability guarantees.</description><pubDate>Fri, 07 Nov 2025 19:46:59 GMT</pubDate><content:encoded>&lt;p&gt;Azure Cosmos DB for NoSQL is a general JSON database with a rich SQL-like interface, multi-region deployments (including multi-region writes), and &lt;a href=&quot;https://learn.microsoft.com/en-us/azure/reliability/reliability-cosmos-db-nosql&quot;&gt;strong availability guarantees&lt;/a&gt;. Cosmos DB has a usage-based billing model and has high elasticity - the database can dynamically scale or auto-scale from next-to-0 to ChatGPT.&lt;/p&gt;
&lt;p&gt;One of the most common migration paths to Cosmos DB is from AWS DynamoDB. DynamoDB is a massively scalable key-value store used internally in AWS for many vital services. While both DynamoDB and Cosmos DB are serverless NoSQL databases, they have a lot of differences: data model, access patterns, multi-region deployment options, consistency guarantees.&lt;/p&gt;
&lt;p&gt;For users wanting to explore Cosmos DB or migrate their production workloads from DynamoDB or other databases, Dsync is a perfect solution that makes the process seamless. &lt;strong&gt;You can migrate 100’s of GB’s of data in a few hours with one simple command.&lt;/strong&gt; For smaller databases, you can use our &lt;a href=&quot;https://docs.adiom.io/getting-started/quickstart/dynamo-cosmos&quot;&gt;Open Source single-binary version&lt;/a&gt;. For large migrations and production deployments you can use our &lt;a href=&quot;https://docs.adiom.io/enterprise/running-dsynct/dynamodb-to-cosmos-db-nosql&quot;&gt;scalable Enterprise Dsync&lt;/a&gt; (Dsynct).&lt;/p&gt;
&lt;p&gt;In this white paper we review our approach for online database migrations to Azure Cosmos DB for NoSQL, and we specifically examine the migration path from AWS DynamoDB. The paper covers technical details and the architecture of the migration solution with Dsync, as well as its practical advantages that accelerate and derisk migration projects.&lt;/p&gt;
</content:encoded><category>product</category><category>cosmos-db</category><category>dynamodb</category><category>azure</category><category>aws</category><author>Alexander Komyagin</author></item><item><title>Migrate RDBMS to MongoDB</title><link>https://www.adiom.io/post/migrate-rdbms-to-mongodb/</link><guid isPermaLink="true">https://www.adiom.io/post/migrate-rdbms-to-mongodb/</guid><description>We’re excited to announce the newest addition to our connector family: the “SQL batch” connector.</description><pubDate>Tue, 28 Oct 2025 22:43:02 GMT</pubDate><content:encoded>&lt;p&gt;We’re excited to announce the newest addition to our connector family: the “SQL batch” connector. &lt;a href=&quot;https://github.com/adiom-data/dsync/&quot;&gt;Dsync&lt;/a&gt; with the SQL batch connector makes RDBMS migration to NoSQL significantly easier, while upholding Dsync’s standards of consistency and reliability at scale. By leveraging our Migration AI agent, it streamlines data transformation and the migration process.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The SQL batch connector is now available in Private Preview&lt;/strong&gt;. &lt;a href=&quot;https://www.adiom.io/contact&quot;&gt;Contact us&lt;/a&gt; to try it out.&lt;/p&gt;
&lt;p&gt;Dsync sets a new standard for online database migrations and real-time replication, combining scalability, reliability, ease of use, and unmatched flexibility.&lt;/p&gt;
&lt;h2 id=&quot;connector&quot;&gt;Connector&lt;/h2&gt;
&lt;p&gt;The SQL batch connector lets you specify a custom SQL query on the source database, similar to creating a virtual table. This is especially useful for migrating relational data to MongoDB or other NoSQL databases, where you may need to reshape data to take advantage of the document model.&lt;/p&gt;
&lt;p&gt;Key features:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Supports custom SQL queries&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Supports JSON aggregation in modern SQL engines&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Utilizes advanced JOIN capabilities&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Compatible with both SQL Server and PostgreSQL as sources (including Initial Sync and CDC)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Seamlessly integrates with the Dsync platform and &lt;a href=&quot;https://docs.adiom.io/enterprise/running-dsynct/data-transformations&quot;&gt;transformer&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Offers task-based parallelization and resumability&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Users can use &lt;a href=&quot;https://www.mongodb.com/try/download/relational-migrator&quot;&gt;MongoDB Relational Migrator&lt;/a&gt; for schema mapping and import it into the AI workflow.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;AI-enabled database migration from SQL to MongoDB&lt;/p&gt;
&lt;h2 id=&quot;example-denormalizing-tpc-h-dataset&quot;&gt;Example: Denormalizing TPC-H Dataset&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Source&lt;/strong&gt;: PostgreSQL with 4 CPU and 34 GB RAM (AlloyDB on GCP)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Destination&lt;/strong&gt;: MongoDB v8 Sharded Cluster&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dataset:&lt;/strong&gt; 30GB, ~100 million rows (&lt;a href=&quot;https://www.tpc.org/tpch/&quot;&gt;TPC-H dataset&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;The TPC-H dataset is highly normalized, containing customer, order, part, and supplier data. For our MongoDB target schema, we denormalize the data to optimize queries for customer orders and specific parts.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;TPC-H conceptual schema mapping for denormalization&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2594&quot; height=&quot;884&quot; src=&quot;/_astro/02.BFSJnLXT_Z1cXjaT.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;TPC-H schema mapping&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Generate schema mapping with MongoDB’s Relational Migrator.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img alt=&quot;TPC-H schema mapping for denormalization in Relational Migrator tool&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2534&quot; height=&quot;1334&quot; src=&quot;/_astro/03.BfTLjyvY_Z2vucGt.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Schema mapping in MongoDB Relational Migrator&lt;/p&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;Export the project as a .relmig file and feed it to our Migration AI Agent (based on &lt;a href=&quot;https://factory.ai/&quot;&gt;Factory AI’s Droid&lt;/a&gt; - help us name it! Does &lt;em&gt;Migroid&lt;/em&gt; sound good?).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img alt=&quot;Migration AI agent based on Factory.AI droid&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2895&quot; height=&quot;1833&quot; src=&quot;/_astro/04.C-fA_K3R_22bbDk.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Migration AI Agent&lt;/p&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;The AI agent generates a ready-to-use YAML config for the SQL batch connector, which you can use with Dsync (single-binary or Enterprise) or customize further:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;dsync&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -ns&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;orders:tpch_dsync.orders,customer:tpch_dsync.customer,part:tpch_dsync.part&quot;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; sqlbatch&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --config&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; tpch_migration.yaml&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;MONGODB_UR&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;I&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;TRANSFORME&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;R&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt=&quot;Dsync web interface showing fast parallel processing for SQL to MongoDB migration&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;973&quot; height=&quot;699&quot; src=&quot;/_astro/05.CMkbvk7K_1hKNro.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Dsync Web Progress&lt;/p&gt;
&lt;p&gt;The migration produces the desired document structures in MongoDB. For example, here is the “orders” collection:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Target order document in MongoDB&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1066&quot; height=&quot;1146&quot; src=&quot;/_astro/06.C1kg7UKI_VUQF7.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Target order document in MongoDB&lt;/p&gt;
&lt;h2 id=&quot;performance-analysis&quot;&gt;Performance analysis&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Test Setup:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Source: PostgreSQL (4 CPU, 34 GB RAM, AlloyDB on GCP)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Destination: MongoDB v8 Replica Set (4 CPU, 16 GB RAM)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Dsync VM: 4 CPU, 16 GB RAM and 8 CPU, 32 GB RAM&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Results:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Initial sync with Dsync completes in 40 minutes or less, using 20–25% of source PostgreSQL CPU (takes 20 minutes with 8 CPU Dsync VM, using 60% of source CPU).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;For production, we recommend using a read replica or running migrations during off-hours.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Relational Migrator took 6–8 hours and failed with a connection error at the very end in our runs, despite the source being available and operational.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt=&quot;Dsync is 10-20x faster than MongoDB Relational Migrator and doesn’t fail &quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1196&quot; height=&quot;511&quot; src=&quot;/_astro/07.BhryvW2x_1v6Lb4.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Comparison of run times and status&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;MongoDB Relational Migrator failed the data migration at the very end after 8 hours&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1416&quot; height=&quot;790&quot; src=&quot;/_astro/08.3aRvDZaM_1c0av1.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;MongoDB Relational Migrator Error&lt;/p&gt;
&lt;p&gt;Dsync proved to be 10–20x faster and more reliable than MongoDB Relational Migrator. Despite our initial concerns about running aggregations on the source, this approach has proven to have a manageable impact and offers high flexibility - especially when used with a transformer. It is also more performant than alternatives like constructing final objects on the destination and more practical than building a streaming join engine. Additionally, it allows us to maintain the reliability and integrity standards of the Dsync platform.&lt;/p&gt;
&lt;h2 id=&quot;give-it-a-try&quot;&gt;Give it a try&lt;/h2&gt;
&lt;p&gt;The SQL batch connector is now available in Private Preview. &lt;a href=&quot;https://www.adiom.io/contact&quot;&gt;Contact us&lt;/a&gt; to request access. In upcoming posts, we’ll cover CDC functionality for the SQL batch connector.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/adiom-data/dsync/&quot;&gt;Get Dsync&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.adiom.io/&quot;&gt;Documentation&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><category>guides</category><category>mongodb</category><category>sql</category><category>replication</category><author>Alexander Komyagin</author></item><item><title>Dsync Now Available on Microsoft Azure Marketplace</title><link>https://www.adiom.io/post/dsync-now-available-on-microsoft-azure-marketplace/</link><guid isPermaLink="true">https://www.adiom.io/post/dsync-now-available-on-microsoft-azure-marketplace/</guid><description>Dsync helps enterprises eliminate the complexity and risk of database migrations, offering a secure, high-performance solution that seamlessly moves production workloads between NoSQL and SQL databases - including to Azure Cosmos DB.</description><pubDate>Fri, 17 Oct 2025 16:32:17 GMT</pubDate><content:encoded>&lt;p&gt;We’re thrilled to announce that &lt;strong&gt;Dsync&lt;/strong&gt; is now available in the &lt;strong&gt;Microsoft Azure Marketplace&lt;/strong&gt;, making it easier than ever for Azure customers to deploy, manage, and scale their data migrations and replications.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dsync&lt;/strong&gt; helps enterprises eliminate the complexity and risk of database migrations, offering a secure, high-performance solution that seamlessly moves production workloads between NoSQL and SQL databases - including to &lt;strong&gt;Azure Cosmos DB&lt;/strong&gt;. With built-in resiliency, resumability, and end-to-end data integrity, Dsync transforms what was once a painful, manual process into a fast, reliable, and repeatable experience.&lt;/p&gt;
&lt;p&gt;“Making Dsync available in the Azure Marketplace enables us to reach more organizations looking to simplify and accelerate their data migrations,” said &lt;strong&gt;Alexander Komyagin&lt;/strong&gt;, CEO of Adiom. “Our mission is to make data movement effortless, reliable, and secure - no matter where it runs.”&lt;/p&gt;
&lt;p&gt;This milestone strengthens our collaboration with Microsoft and expands the options available to enterprises building on the Azure platform.&lt;/p&gt;
&lt;p&gt;👉 &lt;strong&gt;Get started today&lt;/strong&gt; — &lt;a href=&quot;https://azuremarketplace.microsoft.com/en/marketplace/apps/adiom.adiom_dsync_vm_dynamo&quot;&gt;Visit Dsync in the Azure Marketplace&lt;/a&gt; and learn how Adiom can help your organization move data faster, safer, and smarter.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.prlog.org/13105527-adiom-dsync-now-available-in-the-microsoft-azure-marketplace.html&quot;&gt;Full Press Release&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.adiom.io/getting-started/quickstart/dynamo-cosmos&quot;&gt;Documentation&lt;/a&gt;&lt;/p&gt;
</content:encoded><category>product</category><category>cosmos-db</category><category>replication</category><category>azure</category><author>Alexander Komyagin</author></item><item><title>100TB HBase to MongoDB in Under 48 Hours: Building Support for Large-Scale Online Production Migration</title><link>https://www.adiom.io/post/hbase-to-mongodb-migration/</link><guid isPermaLink="true">https://www.adiom.io/post/hbase-to-mongodb-migration/</guid><description>Modern enterprises often find themselves needing to migrate massive production datasets between different database technologies.</description><pubDate>Tue, 09 Sep 2025 18:55:52 GMT</pubDate><content:encoded>&lt;p&gt;Modern enterprises often find themselves needing to migrate massive production datasets between different database technologies. Recently, we tackled one of the most challenging scenarios: migrating over 100TB of data containing 100+ billion records from HBase to MongoDB while maintaining active production traffic. In this article we explore how we built the technical foundation to make this possible.&lt;/p&gt;
&lt;h2 id=&quot;the-challenge-scale-meets-complexity&quot;&gt;The Challenge: Scale Meets Complexity&lt;/h2&gt;
&lt;p&gt;The environment presented several unique challenges:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Massive scale&lt;/strong&gt;: 100+ TB of data across billions of records in an active HBase cluster&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Timeline:&lt;/strong&gt; Migration should complete in a &lt;em&gt;reasonable&lt;/em&gt; amount of time&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Zero tolerance for extended downtime&lt;/strong&gt;: Production systems can’t wait months for migration&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Complex data transformation&lt;/strong&gt;: Converting HBase key-value pairs to MongoDB’s Extended JSON format&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Production reliability requirements&lt;/strong&gt;: The migration solution itself must be enterprise-grade&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;hbase-architecture-primer&quot;&gt;HBase Architecture Primer&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;Diagram of Apache HBase architecture showing interactions between Zookeeper, HMaster, Client, and Region Servers with labeled data tables.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;704&quot; height=&quot;400&quot; src=&quot;/_astro/01.DchN6jg4_Z2axayD.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;HBase Architecture Diagram&lt;/p&gt;
&lt;p&gt;HBase is a horizontally scalable column-oriented key-value store. Records are organized into tables. Each record or row is identified by its row key, which has to be unique. The data for that row is represented as key-value pairs, where the key is a column name, and the value is arbitrary binary data (byte[]) - it can be a primitive data type like string, an encoded JSON document, an image, or something else. The columns are grouped into column families which are stored into separate files in the underlying HDFS cluster.&lt;/p&gt;
&lt;p&gt;For scalability, HBase uses Region Servers, where each Region Server hosts data for a set of  particular ranges of row keys that are called Regions. For example, a production HBase cluster can have 32 Region Servers with 256 total Regions, meaning that each Region Server is responsible for 8 Regions.&lt;/p&gt;
&lt;h2 id=&quot;mongodb-architecture-primer&quot;&gt;MongoDB Architecture Primer&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;Diagram showing data flow between driver, mongos, and shards. JSON data example.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;720&quot; height=&quot;460&quot; src=&quot;/_astro/02.DCPH1_aS_kEdzc.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;MongoDB Sharded Cluster and JSON example&lt;/p&gt;
&lt;p&gt;MongoDB is a horizontally scalable document-oriented database. MongoDB documents are records in &lt;a href=&quot;https://www.mongodb.com/docs/manual/reference/mongodb-extended-json/&quot;&gt;Extended JSON&lt;/a&gt; (or BSON), uniquely identified by the _id key. The documents are organized in collections that are logically grouped into databases.&lt;/p&gt;
&lt;p&gt;MongoDB supports high availability with the Replica Set architecture. For horizontal scalability MongoDB leverages sharding and Sharded Clusters, where the data is distributed across two or more Replica Sets (Shards) based on ranges (“chunks”) for a particular Shard Key.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.mongodb.com/products/platform/atlas-database&quot;&gt;MongoDB Atlas&lt;/a&gt; is a fully managed cloud database service that simplifies deploying, scaling, and managing MongoDB databases in the cloud.&lt;/p&gt;
&lt;h2 id=&quot;technical-requirements-for-hbase-to-mongodb-migration&quot;&gt;Technical Requirements for HBase to MongoDB Migration&lt;/h2&gt;
&lt;p&gt;Building a system capable of handling this scale required addressing seven critical requirements:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Minimize Downtime&lt;/strong&gt;: We implemented a CDC (Change Data Capture) stream coordinated with initial data copy to ensure no changes are lost during migration.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Scale and Performance&lt;/strong&gt;: With billions of records, every inefficiency scales exponentially. The migration data path required optimization down to the microsecond level.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Repeatability&lt;/strong&gt;: Large modernization efforts involve iterations across development, UAT, and production environments, demanding consistent, predictable outcomes.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Resumability and Resilience&lt;/strong&gt;: Production migrations must handle failures gracefully without restarting from scratch.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Reverse Sync&lt;/strong&gt;: A cooling-off period after migration requires syncing changes back to HBase with fallback capability.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Observability&lt;/strong&gt;: Real-time progress tracking, ETAs, and performance bottleneck identification are essential for production planning.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Throttling&lt;/strong&gt;: Impact on the source system serving live traffic must be carefully controlled.&lt;/p&gt;
&lt;h2 id=&quot;solving-the-hbase-cdc-challenge&quot;&gt;Solving the HBase CDC Challenge&lt;/h2&gt;
&lt;p&gt;HBase’s architecture presented a unique technical hurdle: it doesn’t support pull-based change streams and only offers push-based replication. Our solution leveraged HBase’s existing replication mechanism with a creative twist:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;We created a “fake” HBase cluster with a modified write path that writes to Kafka instead of storage&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The original HBase cluster replicates to this fake cluster using standard HBase replication&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;This architecture transforms HBase’s push-based replication into Kafka’s pull-based change stream&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Multiple Kafka topics with partitioned streams support high CDC throughput&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;the-dsync-architecture&quot;&gt;The Dsync Architecture&lt;/h2&gt;
&lt;p&gt;Our solution centers on a scalable enterprise-grade architecture built with several key components:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Flowchart showing data flows in dsync. HBase region server nodes link to Kafka, HBase, and MongoDB connectors via dsync workers. Temporal coordinator manages task flow.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1807&quot; height=&quot;753&quot; src=&quot;/_astro/03.De9OMVLX_ZcM4YI.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Scalable Dsync Architecture&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Temporal Workflow Engine&lt;/strong&gt;: Provides durable workflow orchestration for complex, long-running migration processes.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Task-Based Parallelization&lt;/strong&gt;: Work splits into tasks based on source HBase regions, with multiple dsync workers processing tasks in parallel.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;YAML-Based Transformations&lt;/strong&gt;: Data transformations and filtering are defined in YAML using CEL (Common Expression Language), making complex data model adjustments manageable at scale.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Automatic CDC Switching&lt;/strong&gt;: After initial data copy completion, the system automatically switches to replicating CDC changes from the pre-copy timestamp, ensuring zero data loss.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Lightweight deployment:&lt;/strong&gt; Even when deployed at scale, Dsync only uses compute (CPU + RAM) and doesn’t require persistent storage, making it easily deployable on commodity VMs or containers.  &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Observability and Reporting:&lt;/strong&gt; Dsync provides an intuitive web-based real-time progress report along with granular metrics via OpenTelemetry.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Dsync progress report with overall progress bar, detailed statistics, and per-namespace progress breakdown&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2258&quot; height=&quot;1478&quot; src=&quot;/_astro/04.7z2-A34o_Z2d4OUx.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Dsync progress report&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Signoz charts showing migration data processing statistics&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2013&quot; height=&quot;718&quot; src=&quot;/_astro/05.4FSw8DyG_Z1yHl05.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Detailed metrics in SigNoz via OpenTelemetry&lt;/p&gt;
&lt;h2 id=&quot;performance-results&quot;&gt;Performance Results&lt;/h2&gt;
&lt;p&gt;Our technical development has achieved impressive benchmarks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;2 million writes/second&lt;/strong&gt; replication capability to a 7xM200 destination Atlas cluster&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;24-48 hour&lt;/strong&gt; migration window for 100 billion records&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Efficient resource utilization&lt;/strong&gt;: 10 worker nodes (16 CPUs, 64GB RAM each) plus 1 coordinator node (8 CPUs, 32GB RAM)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;best-practices-for-large-scale-migration&quot;&gt;Best Practices for Large-Scale Migration&lt;/h2&gt;
&lt;p&gt;Through this development process, we’ve identified key practices for successful large-scale database migrations:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Plan for Iterations&lt;/strong&gt;: Design for multiple runs across Dev, UAT, and production environments with several dry runs before go-live.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Prioritize Repeatability&lt;/strong&gt;: Use migration solutions that enable fast, consistent execution across different environments.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Balance Accuracy and Speed&lt;/strong&gt;: Develop data reconciliation strategies that acknowledge the trade-offs inherent in large-scale operations.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Modularize Workflows&lt;/strong&gt;: Split large tables into separate workflows for easier operational management.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Size Appropriately&lt;/strong&gt;: Revise production sizing based on actual object sizes discovered during development and testing phases.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Follow MongoDB Ingestion Optimization&lt;/strong&gt;: Overprovision destinations, disable backups during migration, set oplog to fixed size, and build indexes during the CDC phase rather than initial load.&lt;/p&gt;
&lt;h2 id=&quot;looking-forward&quot;&gt;Looking Forward&lt;/h2&gt;
&lt;p&gt;The HBase connector is now available in preview - a major breakthrough for large-scale database migrations. This technology helps companies modernize their databases on a short and predictable timeline, and without compromising operational stability.&lt;/p&gt;
&lt;p&gt;By combining Temporal workflows, intelligent CDC, and highly parallel processing, we’ve built a platform that can handle even the toughest migration challenges. We’re continuing to improve dsync, making migrations that were once impossible now achievable and reliable.&lt;/p&gt;
&lt;p&gt;Make sure to check out the demo video of the migration process:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;The HBase connector is available in preview. For more information about the&lt;/em&gt; &lt;a href=&quot;https://docs.adiom.io/enterprise/scalable-deployment&quot;&gt;&lt;em&gt;scalable deployment&lt;/em&gt;&lt;/a&gt; &lt;em&gt;and dsync, please consult our&lt;/em&gt; &lt;a href=&quot;https://docs.adiom.io/&quot;&gt;&lt;em&gt;documentation&lt;/em&gt;&lt;/a&gt;&lt;em&gt;. If you need assistance with HBase or other database migrations, please&lt;/em&gt; &lt;a href=&quot;https://www.adiom.io/contact&quot;&gt;&lt;em&gt;contact us&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
</content:encoded><category>engineering</category><category>mongodb</category><category>hbase</category><category>replication</category><author>Alexander Komyagin</author></item><item><title>Database migrations. Done Right</title><link>https://www.adiom.io/post/database-migrations-done-right/</link><guid isPermaLink="true">https://www.adiom.io/post/database-migrations-done-right/</guid><description>We recently visited Microsoft Reactor to talk about database migration paths, common pain points and best practices.</description><pubDate>Wed, 11 Jun 2025 21:40:50 GMT</pubDate><content:encoded>&lt;p&gt;We recently visited &lt;a href=&quot;https://developer.microsoft.com/en-us/reactor/&quot;&gt;Microsoft Reactor&lt;/a&gt; to talk about database migration paths, common pain points and best practices. Our CEO, Alex, shared his firsthand experiences and customer stories. While the session was focused on migrations to Azure Cosmos DB, most learnings are transferable to other migrations paths:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Pick a tool that makes the process easy, fast and repeatable&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Paradox: a 10-hour migration is much longer than 10x 1-hour migrations&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Assign a migration “champion”&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;One &lt;strong&gt;technical&lt;/strong&gt; person responsible for the planning and project execution&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Get a one-time prod data load as soon as possible to the destination for testing&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Can be a redacted sample. But needs to be &lt;strong&gt;truly representative&lt;/strong&gt; in terms of size and form of the data that you will be migrating&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Keep things as simple as possible with few moving parts in the process.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Doing something complex might be exciting and is good material for a blog post, but &lt;strong&gt;in production best things are usually boring&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Do dry-runs. Lots of them.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If your &lt;em&gt;dry run&lt;/em&gt; is a long and painful process with an uncertain outcome, your production run will be even worse.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Over-provision on the destination as much as possible for the migration.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Write throughput on the destination is typically the biggest bottleneck for large datasets.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Adiom is Microsoft’s trusted partner for migration solutions that enable seamless online database migrations from MongoDB to Cosmos DB vCore, and DynamoDB to Cosmos DB for NoSQL.&lt;/p&gt;
&lt;p&gt;For more information on these migrations, visit the Quickstart page in our documentation: &lt;a href=&quot;https://docs.adiom.io/getting-started/quickstart&quot;&gt;https://docs.adiom.io/getting-started/quickstart&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Session recording and slides:&lt;/p&gt;
</content:encoded><category>strategy</category><category>mongodb</category><category>cosmos-db</category><category>dynamodb</category><category>azure</category><author>Alexander Komyagin</author></item><item><title>Migrating MongoDB Data to FerretDB with dsync</title><link>https://www.adiom.io/post/migrating-mongodb-data-to-ferretdb-with-dsync/</link><guid isPermaLink="true">https://www.adiom.io/post/migrating-mongodb-data-to-ferretdb-with-dsync/</guid><description>This is a slightly modified version of the article on FerretDB&apos;s blog. FerretDB is an open-source alternative and a drop-in replacement for MongoDB.</description><pubDate>Sat, 19 Apr 2025 02:05:44 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;This is a slightly modified version of the article on&lt;/em&gt; &lt;a href=&quot;https://blog.ferretdb.io/migrate-mongodb-data-ferretdb-dsync/&quot;&gt;&lt;em&gt;FerretDB’s blog&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;FerretDB is an open-source alternative and a drop-in replacement for MongoDB. FerretDB implements MongoDB’s wire protocol as a proxy layer over PostgreSQL with DocumentDB extension as the backend. You can read more about it in the &lt;a href=&quot;https://github.com/FerretDB/FerretDB&quot;&gt;GitHub repo&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For users looking to migrate data from MongoDB to FerretDB, ensuring a smooth transition is crucial.&lt;/p&gt;
&lt;p&gt;Traditional migration workflows often rely on static dumps and manual restoration steps, which can often lead to complications. Skipped collections. Metadata mismatches. Data loss. And worst of all – no clue where things went wrong.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/adiom-data/dsync/&quot;&gt;dsync&lt;/a&gt; by &lt;a href=&quot;https://adiom.com/&quot;&gt;Adiom&lt;/a&gt; is a tool that connects directly to both the source and destination of MongoDB-compatible services and streams data in real time. It seamlessly handles both the initial sync and live replication, continuously monitoring for any changes and updating the destination database accordingly. Using dsync, users can easily migrate their data from MongoDB to FerretDB - as easy as running a command in the terminal.&lt;/p&gt;
&lt;p&gt;In this post, we’ll review how to use dsync to migrate the data from MongoDB to a running FerretDB instance.&lt;/p&gt;
&lt;h2 id=&quot;prerequisites&quot;&gt;Prerequisites&lt;/h2&gt;
&lt;p&gt;Make sure to have the following ready before you start:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.ferretdb.io/installation/ferretdb/&quot;&gt;Running FerretDB instance&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Running MongoDB instance (local or remote).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;download-dsync&quot;&gt;Download dsync&lt;/h2&gt;
&lt;p&gt;Download the latest release of dsync from the &lt;a href=&quot;https://github.com/adiom-data/dsync/releases/latest&quot;&gt;GitHub Releases page&lt;/a&gt;. For Mac users, you may need to configure a security exception to execute the binary by &lt;a href=&quot;https://support.apple.com/en-ca/guide/mac-help/mh40616/mac&quot;&gt;following these steps&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Alternatively, you can build dsync from the source code.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;git&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; clone&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; https://github.com/adiom-data/dsync.git&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;cd&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; dsync&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;go&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; build&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;run-dsync-to-migrate-into-ferretdb&quot;&gt;Run dsync to migrate into FerretDB&lt;/h2&gt;
&lt;p&gt;To migrate data from your local MongoDB instance to FerretDB, simply specify the source and destination connection strings.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;MongoDB is running locally at &lt;strong&gt;mongodb://&lt;/strong&gt;&lt;a href=&quot;http://localhost:27018/&quot;&gt;&lt;strong&gt;localhost:27018/&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;FerretDB is running at &lt;strong&gt;mongodb://&lt;username&gt;:&lt;password&gt;@&lt;/strong&gt;&lt;a href=&quot;http://localhost:27017&quot;&gt;&lt;strong&gt;localhost:27017&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Set the following environment variables for the source and destination connection strings and run dsync to migrate all data:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;export&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; MDB_SRC&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;mongodb://localhost:27018/&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;export&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; FERRETDB_DEST&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;mongodb://&amp;lt;username&amp;gt;:&amp;lt;password&amp;gt;@localhost:27017/&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;./dsync&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --progress&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --logfile&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; dsync.log&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;$MDB_SRC&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;$FERRETDB_DEST&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Replace &lt;strong&gt;&lt;username&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;password&gt;&lt;/strong&gt; with your FerretDB credentials. When running FerretDB without authentication enabled, they can be omitted.&lt;/p&gt;
&lt;p&gt;When dsync is running, it opens a live-change monitoring session in the terminal to track the progress of the migration.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Dsync Progress Report : ChangeStream&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Time Elapsed: 00:12:50        1/1 Namespaces synced&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Processing change stream events&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The session will remain open for as long as dsync is running. So even if new data is added to the source MongoDB instance, dsync will keep track of it and replicate it to FerretDB.&lt;/p&gt;
&lt;p&gt;Lastly, confirm that the data has been migrated successfully by connecting to the FerretDB instance and checking the data, or running dsync with the &lt;a href=&quot;https://docs.adiom.io/implementation-details/verification&quot;&gt;verify option&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Have any questions about the migration process? &lt;a href=&quot;https://www.adiom.io/contact&quot;&gt;Contact us&lt;/a&gt; – we’re happy to help.&lt;/p&gt;
</content:encoded><category>guides</category><category>mongodb</category><category>sql</category><category>documentdb</category><category>ferretdb</category><category>replication</category><author>Alexander Komyagin</author></item><item><title>MongoDB + Weaviate = ♥</title><link>https://www.adiom.io/post/mongodb-weaviate/</link><guid isPermaLink="true">https://www.adiom.io/post/mongodb-weaviate/</guid><description>In today&apos;s data-driven world, implementing advanced search functionality can give your business a significant competitive advantage.</description><pubDate>Tue, 18 Mar 2025 03:13:14 GMT</pubDate><content:encoded>&lt;p&gt;In today’s data-driven world, implementing advanced search functionality can give your business a significant competitive advantage. Let’s explore how combining MongoDB with Weaviate creates a powerful solution for modern search needs.&lt;/p&gt;
&lt;h2 id=&quot;understanding-the-technologies&quot;&gt;Understanding the Technologies&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://mongodb.com/&quot;&gt;&lt;strong&gt;MongoDB&lt;/strong&gt;&lt;/a&gt; is a flexible NoSQL database that excels at storing document-oriented data with dynamic schemas, making it ideal for diverse applications.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://weaviate.io/&quot;&gt;&lt;strong&gt;Weaviate&lt;/strong&gt;&lt;/a&gt; is an open-source vector database specialized in storing and querying high-dimensional vectors, enabling semantic search capabilities.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Vector indexes&lt;/strong&gt; organize embeddings (mathematical representations of data) that capture semantic meaning, allowing for similarity-based searches rather than exact matching.&lt;/p&gt;
&lt;h3 id=&quot;why-vector-search-matters&quot;&gt;Why Vector Search Matters&lt;/h3&gt;
&lt;p&gt;Vector search powers several key applications across industries:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Semantic search for context-based document retrieval&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Personalized recommendation systems&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Anomaly detection for security and quality control&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Enhanced conversational AI and chatbots&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;mongodb-vs-weaviate-5-key-differences&quot;&gt;MongoDB vs. Weaviate: 5 Key Differences&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Deployment&lt;/strong&gt;: Weaviate offers easier self-hosting, while MongoDB’s vector capabilities are primarily available through Atlas&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Performance and Features&lt;/strong&gt;: Weaviate is optimized specifically for vector operations and offers important features right out of the box, such as embedding service and hybrid search&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Integration&lt;/strong&gt;: MongoDB simplifies management by storing operational and vector data together&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Cost Structure&lt;/strong&gt;: Weaviate’s open-source nature may offer cost advantages&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Support Ecosystem&lt;/strong&gt;: MongoDB has a larger community, while Weaviate has specialized vector search expertise&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;why-use-both-together&quot;&gt;Why Use Both Together?&lt;/h2&gt;
&lt;p&gt;Rather than viewing this as an either/or decision, consider the benefits of integration:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Complementary Strengths&lt;/strong&gt;: MongoDB handles diverse data structures and complex queries, while Weaviate excels at semantic search and vector operations. The combination enables vector search on self-managed or community MongoDB versions.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Performance Isolation&lt;/strong&gt;: Separating workloads allows each system to focus on its strengths, improving overall system availability and cost-efficiency.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cost Benefits&lt;/strong&gt;: Despite managing two systems, the specialized capabilities can optimize resource utilization and reduce development time.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Future-Proofing&lt;/strong&gt;: A combined approach provides flexibility to adapt to evolving data requirements and technological advancements.&lt;/p&gt;
&lt;h2 id=&quot;replication-options&quot;&gt;Replication Options&lt;/h2&gt;
&lt;p&gt;To integrate these systems, consider these data replication methods:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Kafka-Debezium&lt;/strong&gt;: Robust but infrastructure-heavy&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Custom Python Scripts&lt;/strong&gt;: Flexible but introduces maintenance risks&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;SaaS Tools&lt;/strong&gt; (Airbyte, Fivetran): Convenient but potentially clunky&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Dsync&lt;/strong&gt;: A lightweight solution offering simple, fast, and reliable real-time replication with minimal overhead. We recently added a preview version for Weaviate sink – &lt;a href=&quot;https://www.adiom.io/contact&quot;&gt;contact us&lt;/a&gt; if you’re interested in giving it a try!&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By combining MongoDB and Weaviate, you can create a data architecture that leverages the best of both worlds for more powerful, efficient, and future-ready search capabilities.&lt;/p&gt;
</content:encoded><category>engineering</category><category>mongodb</category><category>vector</category><category>replication</category><author>Alexander Komyagin</author></item><item><title>Migrate from Cosmos DB RU for MongoDB: vCore or Atlas?</title><link>https://www.adiom.io/post/migrate-from-cosmos-db-ru-for-mongodb-vcore-or-atlas/</link><guid isPermaLink="true">https://www.adiom.io/post/migrate-from-cosmos-db-ru-for-mongodb-vcore-or-atlas/</guid><description>In today&apos;s cloud-native world, choosing the right database infrastructure is critical for application performance, cost management, and operational efficiency.</description><pubDate>Fri, 28 Feb 2025 20:30:47 GMT</pubDate><content:encoded>&lt;p&gt;In today’s cloud-native world, choosing the right database infrastructure is critical for application performance, cost management, and operational efficiency. Microsoft’s Cosmos DB has been a popular choice for organizations needing globally distributed, multi-model database services. However, many users have faced challenges with performance and the Request Unit (RU) pricing model, leading to increased interest in alternative solutions.&lt;/p&gt;
&lt;p&gt;In this post we explore the migration path from Cosmos DB RU for MongoDB to the newer Cosmos DB vCore for MongoDB option, including common challenges, alternative solutions, and a streamlined migration approach using &lt;a href=&quot;https://github.com/adiom-data/dsync/&quot;&gt;dsync&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;A typical Cosmos DB migration planning session&lt;/p&gt;
&lt;h2 id=&quot;common-challenges-with-the-ru-model-for-mongodb&quot;&gt;Common Challenges with the RU Model for MongoDB&lt;/h2&gt;
&lt;p&gt;While Cosmos DB’s RU for MongoDB model excels at elastic scalability and point reads, it presents several key challenges:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Unpredictable Pricing:&lt;/strong&gt; The consumption-based RU model can make costs difficult to forecast, especially for workloads with variable traffic patterns. Many organizations find themselves over-provisioning to avoid performance issues, resulting in higher costs than necessary. Cosmos RU supports auto-scaling that can help to mitigate some of the performance impacts, but it doesn’t scale down to 0 and the lower bound depends on the data size and the maximum allowed RU set.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Performance Limitations:&lt;/strong&gt; For data-intensive operations like large-scale data ingestion or scan-heavy workloads, the RU model often requires substantial provisioning, which can become prohibitively expensive. It also requires knowing in advance which collections need to be sharded with what shard key.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Limited Change Stream (CDC) Support&lt;/strong&gt;: Cosmos DB RU only supports creating a change stream for individual collections, and it doesn’t generate change events for delete operations. This is often a major limiting factor for event-driven architectures.&lt;/p&gt;
&lt;h2 id=&quot;alternative-options&quot;&gt;Alternative Options&lt;/h2&gt;
&lt;p&gt;When considering alternatives to Cosmos DB RU for MongoDB, several options emerge:&lt;/p&gt;
&lt;h3 id=&quot;self-managed-mongodb&quot;&gt;&lt;a href=&quot;https://www.mongodb.com/try/download/community-edition&quot;&gt;Self-Managed MongoDB&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Complete control over deployment and configuration&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Potential cost savings for certain workloads&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Lacks many enterprise-grade features&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Requires MongoDB-specific operational expertise&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Higher maintenance overhead&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;mongodb-atlas&quot;&gt;&lt;a href=&quot;https://www.mongodb.com/products/platform/atlas-database&quot;&gt;MongoDB Atlas&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Advanced features including encryption (with queryable encryption)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Robust streaming capabilities and vector search functionality&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Excellent performance characteristics&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Native Document engine and feature-rich queries&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Limited deployment flexibility (minimum of 3 nodes required)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Introduces a new vendor into your infrastructure ecosystem if you’re not already using MongoDB&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;cosmos-db-vcore-for-mongodbnew-option&quot;&gt;&lt;a href=&quot;https://learn.microsoft.com/en-us/azure/cosmos-db/mongodb/vcore/&quot;&gt;Cosmos DB vCore for MongoDB&lt;/a&gt; (New Option)&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;PostgreSQL-based architecture&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Open-source engine with available &lt;a href=&quot;https://github.com/microsoft/documentdb&quot;&gt;repository&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Integrated vector database capabilities&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Seamless integration with other Azure products and services&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Supports single-node deployment for cost optimization&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Familiar MongoDB compatibility&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Not all MongoDB features and query operators are supported&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Some performance optimizations are still a work in progress&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;seamless-online-cosmos-db-migration-with-dsync&quot;&gt;Seamless Online Cosmos DB Migration with dsync&lt;/h2&gt;
&lt;p&gt;The most straightforward path to migrate from Cosmos DB RU to vCore for MongoDB or MongoDB is using the &lt;a href=&quot;https://github.com/adiom-data/dsync/&quot;&gt;dsync&lt;/a&gt; tool. This approach simplifies and accelerates what would otherwise be a lengthy and complex migration process. What would take many hours with dump-restore, now takes minutes!&lt;/p&gt;
&lt;p&gt;Basic migration syntax:&lt;/p&gt;
&lt;p&gt;dsync $COSMOS_RU $COSMOS_VCORE&lt;/p&gt;
&lt;p&gt;You can find additional details, examples and configuration options in &lt;a href=&quot;https://docs.adiom.io&quot;&gt;dsync documentation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Developed by &lt;a href=&quot;https://www.adiom.io/&quot;&gt;Adiom&lt;/a&gt;, dsync is an open-source tool designed to make online NoSQL database migrations remarkably simple for developers and DevOps teams. Inspired by the simplicity of the familiar “rsync” tool for file operations, dsync brings that same ease of use to online database migrations.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key Features of dsync:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Lightweight:&lt;/strong&gt; Minimal resource requirements&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Highly Parallelized:&lt;/strong&gt; Optimized for performance during migrations&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Reliable:&lt;/strong&gt; Includes resumability and robust data validation checks&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Portable:&lt;/strong&gt; Runs anywhere - from your laptop to a VM or Docker container&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;User-Friendly:&lt;/strong&gt; Zero learning curve for anyone familiar with basic bash commands&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The dsync tool automates both initial data synchronization and change data capture (CDC), managing the coordination and transition between these phases without manual intervention.&lt;/p&gt;
&lt;h2 id=&quot;migration-considerations&quot;&gt;Migration Considerations&lt;/h2&gt;
&lt;p&gt;Even when migrating between MongoDB-compatible APIs, several factors require special attention:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Indexes&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Ensure your index strategy is properly transferred and optimized for the new environment. Different MongoDB implementations have subtle differences in indexing behavior.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Performance Validation&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Thoroughly test query and write performance under your expected load patterns. The vCore model’s performance characteristics will differ from your RU-based deployment.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Data Integrity&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Decide what approach to use for validating data integrity post-migration. This is especially critical for online migrations. Our CEO’s &lt;a href=&quot;https://medium.com/@adkomyagin/validating-data-like-a-pro-post-migration-integrity-d06300d6bfb8&quot;&gt;post&lt;/a&gt; on Medium has a good summary of common methods. Dsync already includes embedded validation checks based on counts and document hash (&lt;a href=&quot;https://docs.adiom.io/implementation-details/verification#legacy-verification&quot;&gt;docs&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;NOTE for &lt;strong&gt;Cosmos vCore&lt;/strong&gt; destinations: the &lt;a href=&quot;https://www.mongodb.com/docs/manual/reference/method/db.collection.estimatedDocumentCount/&quot;&gt;collection.estimatedDocumentCount()&lt;/a&gt; method may return incorrect counts after migrating a large data set. We recommend using using the count() or countDocuments() methods that return accurate information but may take a little longer.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Delete Operations&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Note that Cosmos DB doesn’t expose deletes in its change stream, which can present a challenge during migration if you’re looking to minimize downtime (so-called live or online migration). Ideally, you should pause or queue delete operations at the application level during migration. If that’s not possible and you are migrating to Cosmos DB vCore for MongoDB, the Adiom team offers specialized support.&lt;/p&gt;
&lt;h2 id=&quot;best-practice&quot;&gt;Best Practice&lt;/h2&gt;
&lt;p&gt;For a successful migration, replicate the entire migration process across all environments, starting with development moving through your testing environments before tackling production. This approach helps identify and resolve any migration-specific issues early in the process.&lt;/p&gt;
&lt;p&gt;The portability of dsync makes it particularly well-suited for this progressive migration strategy, allowing you to establish and refine your migration playbook with minimal effort.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;As organizations look to optimize their database infrastructure for performance and cost, the migration from Cosmos DB RU to vCore for MongoDB represents an attractive option. With the right tools and approach, this migration can be executed with minimal disruption to your applications and operations.&lt;/p&gt;
&lt;p&gt;The dsync tool simplifies this journey, bringing rsync-like simplicity to what would otherwise be a complex database migration process. Whether you’re looking to reduce costs, improve performance for specific workloads, or gain more deployment flexibility, the new vCore option deserves serious consideration.&lt;/p&gt;
&lt;p&gt;If you need assistance with a migration, help with evaluating options, or simply want more information about dsync, please &lt;a href=&quot;https://www.adiom.io/contact&quot;&gt;reach out&lt;/a&gt; to the our team as we are continuing to enhance this open-source tool for the benefit of the broader database community.&lt;/p&gt;
</content:encoded><category>guides</category><category>mongodb</category><category>cosmos-db</category><category>sql</category><category>vector</category><category>replication</category><author>Alexander Komyagin</author></item><item><title>Online migration from DynamoDB to CosmosDB NoSQL</title><link>https://www.adiom.io/post/online-migration-from-dynamodb-to-cosmosdb-nosql/</link><guid isPermaLink="true">https://www.adiom.io/post/online-migration-from-dynamodb-to-cosmosdb-nosql/</guid><description>We&apos;re excited to announce the public preview of DynamoDB and Cosmos DB NoSQL support in dsync, a powerful tool that revolutionizes database migration workflows.</description><pubDate>Tue, 18 Feb 2025 06:08:51 GMT</pubDate><content:encoded>&lt;p&gt;We’re excited to announce the public preview of DynamoDB and Cosmos DB NoSQL support in &lt;a href=&quot;https://github.com/adiom-data/dsync/&quot;&gt;dsync&lt;/a&gt;, a powerful tool that revolutionizes database migration workflows. This new capability enables seamless, online migration from AWS DynamoDB to Azure Cosmos DB NoSQL, eliminating the traditional hurdles of cross-cloud database transitions.&lt;/p&gt;
&lt;h2 id=&quot;dynamodb-vs-cosmos-db-nosql-why-consider-migration&quot;&gt;DynamoDB vs Cosmos DB NoSQL: Why Consider Migration?&lt;/h2&gt;
&lt;p&gt;While both DynamoDB and Cosmos DB NoSQL are powerful NoSQL databases, each offers unique advantages that might better suit your evolving needs. DynamoDB is a key-value store on steroids. It can handle &lt;strong&gt;massive scale&lt;/strong&gt; (a lot of internal AWS services are using it), but it uses its own specific query language and the number of supported features is rather limited.&lt;/p&gt;
&lt;p&gt;Azure Cosmos DB NoSQL provides multi-region writes, automatic indexing, and more flexible consistency levels, making it particularly attractive for globally distributed applications. It also supports a flavor of SQL as a query language, and it integrates seamlessly with other Azure services, potentially simplifying your cloud infrastructure if you’re already invested in the Azure ecosystem or planning to move from AWS to Azure.&lt;/p&gt;
&lt;h2 id=&quot;the-old-way-offline-migration-headaches&quot;&gt;The Old Way: Offline Migration Headaches&lt;/h2&gt;
&lt;p&gt;Traditionally, migrating from DynamoDB to CosmosDB involved a complex, time-consuming export-import process with cloud storage and a data processing framework. For example, it could be the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Export data from DynamoDB to S3&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Set up and configure Spark clusters&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Transform and load data into Cosmos DB&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Plan for significant application downtime&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This approach required extensive planning, specialized expertise, and often resulted in prolonged service interruptions.&lt;/p&gt;
&lt;h2 id=&quot;the-new-way-streamlined-online-migration-from-dynamodb-to-cosmosdb-with-dsync&quot;&gt;The New Way: Streamlined Online Migration from DynamoDB to CosmosDB with dsync&lt;/h2&gt;
&lt;p&gt;Dsync transforms this entire process into a straightforward operation that any developer or DevOps engineer can perform. Here’s what makes it special:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Zero Infrastructure Requirements&lt;/strong&gt;: Runs directly on your local machine or VM&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;No Data Storage&lt;/strong&gt;: Processes data in-memory without persistent storage&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Familiar Unix-like Syntax&lt;/strong&gt;: If you know basic shell commands, you already know how to use dsync&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Online Migration&lt;/strong&gt;: Minimal to no downtime required&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Cross-Cloud Security&lt;/strong&gt;: Simplified authentication process&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here’s how simple it becomes:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;## Start Cosmos DB Sink Connector&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;cosmos-sink&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 8089&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; $URL $KEY &amp;amp;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;## Login to AWS CLI&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;aws&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; sso&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; login&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;## Run dsync&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;dsync&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --progress&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --logfile&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; dsync.log&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --namespace&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;TABLENAM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;E&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;D&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;B&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;CONTAINE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;R&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; dynamodb&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; grpc://localhost:8089&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --insecure&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;learn-more&quot;&gt;Learn more&lt;/h2&gt;
&lt;p&gt;You can learn more in our &lt;a href=&quot;https://docs.adiom.io/getting-started/quickstart/dynamo-cosmos&quot;&gt;QuickStart guide&lt;/a&gt; or by watching the demo video on &lt;a href=&quot;https://youtu.be/1my4Pg-lpC8&quot;&gt;YouTube&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Ready to simplify your database migration? Try dsync today and experience the future of seamless cross-cloud data synchronization.&lt;/p&gt;
</content:encoded><category>guides</category><category>cosmos-db</category><category>dynamodb</category><category>azure</category><category>aws</category><author>Alexander Komyagin</author></item><item><title>Online vs. Offline Database Migrations: Which Path is Right for You?</title><link>https://www.adiom.io/post/online-vs-offline-database-migrations-which-path-is-right-for-you/</link><guid isPermaLink="true">https://www.adiom.io/post/online-vs-offline-database-migrations-which-path-is-right-for-you/</guid><description>Database migrations are a necessary evil in the life of any growing application or a company.</description><pubDate>Mon, 23 Dec 2024 01:41:33 GMT</pubDate><content:encoded>&lt;p&gt;Database migrations are a necessary evil in the life of any growing application or a company. They’re often complex, stressful, and, if not handled correctly, can lead to major headaches. One of the first critical decisions you’ll face is choosing between an &lt;strong&gt;offline&lt;/strong&gt; or &lt;strong&gt;online&lt;/strong&gt; migration strategy. Both have their pros and cons, and the best choice will depend on your specific needs, resources, and risk tolerance.&lt;/p&gt;
&lt;p&gt;Let’s break down the key considerations and when each approach shines.&lt;/p&gt;
&lt;h2 id=&quot;the-essentials-shared-concerns-for-all-migrations&quot;&gt;The Essentials: Shared Concerns for All Migrations&lt;/h2&gt;
&lt;p&gt;Before we dive into online vs. offline, let’s cover common ground. These are things to think about no matter which migration method you choose:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Speed and Throughput:&lt;/strong&gt; How long d? This depends on the number of records, their size, latency between systems, network bandwidth, write capacity of your destination database, and the parallelism of the migration tooling that you will choose. Migration speed and throughput aren’t simply linear calculations. Think of it like moving houses – the time it takes depends not just on how much stuff you have, but also on the size of the moving truck, the distance between houses, and how quickly you can unpack at the new location.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Pro-tip: Put your migration host in the same region as your databases, and over-provision your destination to handle the initial surge of writes.&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Careful Planning:&lt;/strong&gt; Always start with your lower environments (dev, QA). Run dry runs on production to simulate real-world data migration scenarios and identify any hidden issues. &lt;em&gt;You don’t want surprises when you’re moving your most important data.&lt;/em&gt; Differences between production and lower environments are common, so be vigilant about schema and data type discrepancies.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Testing, Testing, 1-2-3:&lt;/strong&gt; Don’t just verify functionality in the new database! Run performance tests to see how your queries and operations are performing. Changes in database technology – even version upgrades – can drastically impact performance.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;The Escape Hatch: Rollback Planning:&lt;/strong&gt; While it’s rare to actually roll &lt;em&gt;back&lt;/em&gt; a migration, having a fallback plan is crucial for risk mitigation. It’s like having a parachute – you may never use it, but you’re darn glad it’s there.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Data Integrity Validation:&lt;/strong&gt; Validate your data with checks like count comparisons, full database/table hashes, and spot checks. Find that balance between risk, downtime and migration duration. Sometimes, a combination of methods is need. Note that most off-the-shelf tools don’t help you validate, placing this burden on the user.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Migration Resumability:&lt;/strong&gt; Can you stop and resume the process, or do you need to start over? This has massive implications for how you plan your migration window, so think about this carefully.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Indexes: A Hidden Time Sink:&lt;/strong&gt; Migrations can be a fantastic opportunity to optimize your indexes. It may even be required, as some databases need different indexing strategies, e.g. Cosmos DB and MongoDB. Should you create indexes &lt;em&gt;before&lt;/em&gt; or &lt;em&gt;after&lt;/em&gt; the data copy? For small datasets, it doesn’t matter as much. But for larger datasets, you are best to build them &lt;em&gt;after&lt;/em&gt; the initial copy to avoid write amplification and make sure that index sizes stay on the smaller side.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Cost:&lt;/strong&gt; Mission-critical migrations take time, effort, and money. While it may be tempting to consider them a one-off expense, it’s a project with many variables, that can easily stretch into months. The more variables you can identify and control, the smoother the project will run. We recommend opting for an optimized self-service migration tool that can help you iterate fast. In our experience, this helps reduce project timelines from months into weeks.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;offline-migrations-the-big-bang-approach&quot;&gt;Offline Migrations: The “Big Bang” Approach&lt;/h2&gt;
&lt;p&gt;Offline migrations involve taking your source system offline, moving all the data, and then bringing the new system online. Just like backup and restore. It’s straightforward in concept but comes with some caveats.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;When Offline Migrations Work Best:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Lower Environments:&lt;/strong&gt; Ideal for development, testing and QA environments.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Tolerance for Downtime:&lt;/strong&gt; You can afford a service interruption.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Minimizing Variables:&lt;/strong&gt; You want to avoid the added complexity of online migrations.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Smaller Datasets:&lt;/strong&gt; Typically suitable for under 100GB or under a million records/documents.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;online-migrations-the-seamless-transition&quot;&gt;Online Migrations: The Seamless Transition&lt;/h2&gt;
&lt;p&gt;Online migrations strive for zero or minimal downtime by migrating the data while the source system remains active. &lt;a href=&quot;https://www.adiom.io/post/building-a-repeatable-solution-for-cosmos-db-to-mongodb-migration&quot;&gt;Typically&lt;/a&gt; they involve an initial data copy followed by a streaming changes in real-time from the source to the destination. This is ideal for applications that can’t tolerate service disruptions.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;When Online Migrations Work Best:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Minimize Downtime:&lt;/strong&gt; Essential for mission-critical applications, SaaS products, e-commerce platforms, or anywhere a prolonged outage has severe financial implications.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Large Data Sets:&lt;/strong&gt; Suitable for 100s of GB or 10s of millions of records or more.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Testing In Parallel:&lt;/strong&gt; Allows running the old and new systems concurrently for pre-cutover validation.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;reference-common-migration-tooling-for-migrating-mongodb-azure-cosmos-db-or-aws-documentdb&quot;&gt;Reference: Common Migration Tooling for Migrating MongoDB, Azure Cosmos DB, or AWS DocumentDB&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.mongodb.com/docs/manual/tutorial/backup-and-restore-tools/&quot;&gt;&lt;strong&gt;mongodump + mongorestore&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt; A reliable offline MongoDB solution that can process multiple namespaces in parallel.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.mongodb.com/products/platform/migrate&quot;&gt;&lt;strong&gt;MongoDB Live Migrate&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt; A good option for live migrations &lt;em&gt;to&lt;/em&gt; MongoDB Atlas, but with limitations.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.mongodb.com/docs/cluster-to-cluster-sync/current/reference/mongosync/&quot;&gt;&lt;strong&gt;MongoDB’s mongosync&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt; A newer tool for MongoDB replication and online migrations. It offers a high level of parallelization and a REST interface, and only works for native MongoDB databases 6.0+.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.mongodb.com/docs/atlas/reference/mongomirror/&quot;&gt;&lt;strong&gt;MongoDB’s mongomirror&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt; As an predecessor of mongosync, it supports online migrations for native MongoDB databases, and supports older MongoDB versions going back to 2.6, but it has many limitations such as single threaded CDC and it doesn’t work with sharded clusters.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://azure.microsoft.com/en-us/products/data-factory&quot;&gt;&lt;strong&gt;Azure Data Factory&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;&amp;amp;&lt;/strong&gt; &lt;a href=&quot;https://aws.amazon.com/dms/&quot;&gt;&lt;strong&gt;AWS DMS&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt; Easy-to-use web-based solutions for Azure and AWS, respectively. As managed solutions, they are not available for local deployments, require specific firewall configuration, have performance and other limitations.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://debezium.io/documentation/reference/stable/architecture.html&quot;&gt;&lt;strong&gt;Kafka + Debezium&lt;/strong&gt;&lt;/a&gt;: A very flexible solution that requires custom code, orchestration and Kafka infrastructure.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;3rd Party ETL Solutions (Airbyte, NiFi, Fivetran, etc.):&lt;/strong&gt; Generally complex, not optimized for database migrations. They carry performance, cost and data security limitations.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/adiom-data/dsync/&quot;&gt;&lt;strong&gt;Dsync&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt; A single binary that enables online migrations between different databases by seamlessly incorporating both initial data copy and CDC (change data capture) for replicating changes from the source to the destination. Dsync parallel design also helps with accelerating the initial data copy by 10x for large data sets, thus allowing users to execute a simple offline migration where otherwise they would have to do it online.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;making-the-choice&quot;&gt;Making the choice&lt;/h2&gt;
&lt;p&gt;Your migration strategy should align with your specific circumstances and requirements. Consider online migrations when downtime must be minimized and your dataset is substantial. Opt for offline migrations when simplicity and risk reduction take precedence, particularly with smaller datasets or non-production environments. If you’re not sure, try the offline approach first.&lt;/p&gt;
&lt;p&gt;The landscape of migration tools continues to evolve, with solutions ranging from cloud provider offerings like Azure Data Factory and AWS Data Migration Service to specialized tools like &lt;a href=&quot;https://github.com/adiom-data/dsync/&quot;&gt;dsync&lt;/a&gt;. Each brings its own strengths and limitations, making it crucial to evaluate them against your specific needs, infrastructure constraints, and performance requirements.&lt;/p&gt;
&lt;p&gt;Remember that successful migrations aren’t just about moving data – they’re about ensuring your application continues to perform optimally while maintaining data integrity throughout the process. Taking time to plan, test, and validate your migration strategy will pay dividends in the form of a smoother, more reliable transition.&lt;/p&gt;
</content:encoded><category>strategy</category><category>mongodb</category><category>cosmos-db</category><author>Alexander Komyagin</author></item><item><title>Benchmarking Data Migration Tools</title><link>https://www.adiom.io/post/benchmarking-data-migration-tools/</link><guid isPermaLink="true">https://www.adiom.io/post/benchmarking-data-migration-tools/</guid><description>This is a slightly modified version of the blog post that our intern, Grace, wrote recently.</description><pubDate>Fri, 22 Nov 2024 19:30:04 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;This is a slightly modified version of the blog post that our intern, Grace, wrote recently. The original blog post can be found&lt;/em&gt; &lt;a href=&quot;https://medium.com/@gracebaek2213/benchmarking-data-migration-tools-1efc4ff697b9&quot;&gt;&lt;em&gt;on Medium&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;For this blog post, we benchmark &lt;a href=&quot;https://github.com/adiom-data/dsync/&quot;&gt;dsync&lt;/a&gt;, an open-source data migration tool designed for NoSQL databases, against popular, industry-standard tools, to see how it stacks up in terms of speed, reliability, and ease of use.&lt;/p&gt;
&lt;p&gt;We’ll walk through the methodology, our experiences with each tool, and the lessons we learned about their strengths, weaknesses, and nuances in data migration.&lt;/p&gt;
&lt;h2 id=&quot;data-migration-tools&quot;&gt;Data Migration Tools&lt;/h2&gt;
&lt;p&gt;We evaluated three frequently used data migration tools alongside dsync. Here’s an overview of each tool:&lt;/p&gt;
&lt;h3 id=&quot;airbyte&quot;&gt;&lt;a href=&quot;https://airbyte.com/&quot;&gt;Airbyte&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Airbyte is a data integration platform that boasts a vast library of over 300 connectors, supporting a wide range of sources and destinations. Its open-source architecture makes it highly customizable, while the Airbyte Cloud offering provides a managed solution for users. Designed to address common data synchronization challenges, Airbyte emphasizes flexibility and extensibility, making it suitable for complex use cases.&lt;/p&gt;
&lt;h3 id=&quot;fivetran&quot;&gt;&lt;a href=&quot;https://www.fivetran.com/&quot;&gt;Fivetran&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Fivetran is a fully managed data integration service known for its “set-it-and-forget-it” philosophy. It automates data pipeline maintenance and schema updates, providing a highly reliable and low-maintenance solution. Fivetran excels in syncing data from traditional databases, SaaS applications, and event streams into centralized data warehouses. With its user-friendly interface and robust error handling, it is often favored by organizations prioritizing stability and minimal manual intervention.&lt;/p&gt;
&lt;h3 id=&quot;estuarydev&quot;&gt;&lt;a href=&quot;http://Estuary.dev&quot;&gt;Estuary.dev&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://Estuary.dev&quot;&gt;Estuary.dev&lt;/a&gt; focuses on real-time data movement and transformation, providing a lightweight solution for integrating sources and destinations. The platform is particularly suited for scenarios requiring low-latency data flows. Its minimalistic design makes setup simple, but the trade-off is reduced visibility and control during migration tasks. &lt;a href=&quot;http://Estuary.dev&quot;&gt;Estuary.dev&lt;/a&gt; is best for small to medium workloads that don’t require extensive monitoring or fine-grained tuning.&lt;/p&gt;
&lt;h2 id=&quot;executive-summary&quot;&gt;Executive Summary&lt;/h2&gt;
&lt;p&gt;Through our tests, we found out that &lt;strong&gt;dsync performs about 5.75x faster than&lt;/strong&gt; &lt;a href=&quot;http://Estuary.dev&quot;&gt;&lt;strong&gt;Estuary.dev&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;, while Airbyte and Fivetran did not work in our tests at all&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Here is a table with the final results:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Data migration performance (initial sync time and catch up time) for popular data migration tools dsync and Estuary.dev&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;720&quot; height=&quot;188&quot; src=&quot;/_astro/01.B0lr7MwH_ZJo25j.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Data migration performance (initial sync time and catch up time) for popular data migration tools dsync and Estuary.dev&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;720&quot; height=&quot;445&quot; src=&quot;/_astro/02.CPGINp7g_p6ClW.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;benchmarking-task&quot;&gt;Benchmarking Task&lt;/h2&gt;
&lt;p&gt;The benchmarking task consisted of comparing the performance of data migration tools by using a Cosmos DB instance as the source and a MongoDB instance as the destination. We used YCSB (Yahoo! Cloud Serving Benchmark) to generate realistic data loads for testing.&lt;/p&gt;
&lt;p&gt;The specific benchmarking steps were as follows:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Download&lt;/strong&gt; &lt;a href=&quot;https://github.com/mongodb-labs/YCSB/tree/production/ycsb-mongodb/mongodb&quot;&gt;&lt;strong&gt;YCSB&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Generate data using YCSB:&lt;/strong&gt; We created a dataset of 10 million documents in a single collection using Workload A. This took a couple of hours to complete.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Initial sync test:&lt;/strong&gt; We performed the initial data sync with the migration tools.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Generate additional data using YCSB:&lt;/strong&gt; We generated an additional 1 million documents to simulate a real-world scenario where new data arrives during an ongoing migration.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Catch-up test:&lt;/strong&gt; We measured how well each tool handled the “catch-up” process, which is effectively the maximum rate of CDC (change data capture) or incremental replication.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This is the environment that we used for the tests:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Source Database:&lt;/strong&gt; Azure Cosmos DB with MongoDB API&lt;/p&gt;
&lt;p&gt;- Provisioning: Configured with 4,000 RUs and Autoscale&lt;/p&gt;
&lt;p&gt;- Indexing: Default indexing settings for MongoDB API&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Destination Database:&lt;/strong&gt; Self-managed MongoDB instance on GCP&lt;/p&gt;
&lt;p&gt;- CPU: 4 vCPUs&lt;/p&gt;
&lt;p&gt;- RAM: 16 GB&lt;/p&gt;
&lt;p&gt;- Single-node replica set configuration&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Virtual Machine:&lt;/strong&gt; GCP&lt;/p&gt;
&lt;p&gt;- CPU: 4 vCPUs&lt;/p&gt;
&lt;p&gt;- RAM: 16 GB&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;tool-1-airbyte&quot;&gt;Tool 1: Airbyte&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;Airbyte UI&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;720&quot; height=&quot;221&quot; src=&quot;/_astro/03.DOCvawx9_1YKTBe.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Setup:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We started with the Airbyte Cloud version, which we were able to access through their &lt;a href=&quot;https://docs.airbyte.com/using-airbyte/getting-started/oss-quickstart&quot;&gt;website&lt;/a&gt; by just creating an account. Adding Cosmos DB as the source via the MongoDB connector worked after some trial and error, but we faced a lot of issues when configuring the destination.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Challenges:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We encountered a format specifier error with the destination configurations. When we traced back to the source code on the Github repository, it seemed to be from a missing argument.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Airbyte configuration error for MongoDB connector&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;720&quot; height=&quot;241&quot; src=&quot;/_astro/04.bNF14sG6_Z2pgST2.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;This issue seemed to be a known bug in the &lt;a href=&quot;https://github.com/airbytehq/airbyte/issues/30504&quot;&gt;Airbyte GitHub repository&lt;/a&gt;, and some people had solved the issue by changing the version of destination to 0.1.9 in settings.&lt;/p&gt;
&lt;p&gt;Unfortunately, the Airbyte Cloud version does not allow direct changes to connector versions. To apply the fix, we had to deploy Airbyte locally — a process that took approximately 45 minutes. Once deployed, we adjusted the settings, toggled TLS encryption, and changed the connector version. Despite these efforts, the syntax error persisted.&lt;/p&gt;
&lt;p&gt;Further complicating matters, we encountered repeated network HTTP errors where Airbyte disconnected with a “temporarily down” message. These errors were frustratingly difficult to debug due to inadequate logging and unclear error messages.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Verdict:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Airbyte is often praised for its wide range of connectors (400+), and for good reason — it supports many data sources and destinations, making it a go-to tool for integration tasks. However, &lt;strong&gt;the tool’s setup complexity, poor error logging, and instability makes it a challenging choice for data migration&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&quot;tool-2-fivetran&quot;&gt;Tool 2: Fivetran&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;Fivetran UI&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;720&quot; height=&quot;333&quot; src=&quot;/_astro/05.CHkXjIzP_ZpluNy.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Setup:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Fivetran did not have an open source code version and we were able to quickstart the application by just creating an account. We were able to successfully configure the source using the “Azure Cosmos DB for MongoDB” connector.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Challenges:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Despite supporting MongoDB as a source, we were disappointed to find that Fivetran didn’t offer MongoDB as a destination. This made it unsuitable for our specific test setup, which required a MongoDB destination.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Verdict:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;While Fivetran excels at handling integrations with many sources and destinations, its limited support for MongoDB left it unfit for our specific use case.&lt;/p&gt;
&lt;h2 id=&quot;tool-3-estuarydev&quot;&gt;Tool 3: &lt;a href=&quot;http://Estuary.dev&quot;&gt;Estuary.dev&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;Estuary.dev UI&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;720&quot; height=&quot;296&quot; src=&quot;/_astro/06.C4kZ6Sgx_Z1n3eAE.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Setup:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Estuary was undoubtedly the easiest to set up among all the SaaS tools that we tested. The source and destination setup worked on the first try without any significant issues.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Results:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Initial Sync:&lt;/strong&gt; 1 hour 9 minutes&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Challenges:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Efficiency:&lt;/strong&gt; While &lt;a href=&quot;http://Estuary.dev&quot;&gt;Estuary.dev&lt;/a&gt; successfully completed the migration, its speed lagged behind other tools.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Lack of Visibility:&lt;/strong&gt; One of the major pain points with Estuary was the lack of feedback during the migration. There were no throughput metrics, error logs, or progress indicators. This made it difficult to know if the migration had started or if it had completed successfully.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;No Pause/Resume:&lt;/strong&gt; There was no option to pause the migration, so we couldn’t measure how well Estuary handled the catch-up time after generating 1 million more documents.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Verdict:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Estuary was the most straightforward tool in terms of setup, but its lack of visibility and control over the migration process made it difficult to evaluate performance in detail. It’s an option for smaller, simpler migrations but lacks the sophistication needed for complex or real-time workloads.&lt;/p&gt;
&lt;h2 id=&quot;tool-4-dsync&quot;&gt;Tool 4: Dsync&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;Dsync Web UI for a database migration&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;720&quot; height=&quot;617&quot; src=&quot;/_astro/07.Da_Zr8nQ_1nUJuA.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Setup:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Finally, we tested &lt;a href=&quot;https://docs.adiom.io/getting-started/quickstart&quot;&gt;dsync&lt;/a&gt;, the open-source migration tool that we develop at Adiom. Given that it’s distributed as a simple standalone binary that can be downloaded in the &lt;a href=&quot;https://github.com/adiom-data/dsync/releases/latest&quot;&gt;Github repo&lt;/a&gt;, there’s no setup difficulties. Testing was conducted on a virtual machine. We tried the default load-level as well as the “Beast” level.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;./dsync&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -s&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; SOURCE&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -d&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; DEST&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -load-level&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; Beast&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Results:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Initial Sync Time:&lt;/strong&gt; 12:40 min&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Catch-up Time:&lt;/strong&gt; 7:54 min&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Challenges:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Catch-Up Efficiency:&lt;/strong&gt; We noticed that the catch-up time for dsync did not decrease even when higher load settings were applied. This is something that the team is investigating and it will be addressed in a future release.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Verdict:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Dsync showed promising performance, especially in terms of efficiency as it was more than 5x faster than Estuary. Further, dsync’s performance and metrics were easily observable, making it easy to track the progress and estimate the time to completion.&lt;/p&gt;
&lt;h2 id=&quot;final-thoughts-benchmarked-data-migration-tools-comparison-and-takeaways&quot;&gt;Final Thoughts: Benchmarked Data Migration Tools Comparison and Takeaways&lt;/h2&gt;
&lt;p&gt;After testing these tools, we have a few key takeaways:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Airbyte&lt;/strong&gt; offers a massive library of connectors, but its error-prone setup and lack of clear diagnostics made it challenging to use.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Fivetran&lt;/strong&gt; is limited in its support for specific use cases like MongoDB.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;http://Estuary.dev&quot;&gt;&lt;strong&gt;Estuary.dev&lt;/strong&gt;&lt;/a&gt; is a convenient option for simple migrations with the easiest setup, but lacks efficiency and key features like logging and pausing/resumability, which makes it difficult to assess and manage large-scale migrations.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Dsync&lt;/strong&gt; is a highly customizable and performant tool, but currently only supports Cosmos DB and MongoDB. We have a preview of DynamoDB support, and are working on other connectors as well. If you would like to give it a try, or talk about the future roadmap, you can get in contact with the team &lt;a href=&quot;https://www.adiom.io/contact&quot;&gt;on the contact page&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ultimately, the right tool depends on the specific requirements of the project, whether it’s ease of use, flexibility, performance under load, or visibility into the migration process.&lt;/p&gt;
&lt;h2 id=&quot;about-the-author&quot;&gt;About the Author&lt;/h2&gt;
&lt;p&gt;Grace is a junior at UC Berkeley, studying Computer Science and Economics. She interned as a software developer at &lt;a href=&quot;https://www.adiom.io/&quot;&gt;Adiom&lt;/a&gt;, where as one of her projects she benchmarked &lt;a href=&quot;https://github.com/adiom-data/dsync/&quot;&gt;dsync&lt;/a&gt;, an open-source data migration tool designed for NoSQL databases, against popular, industry-standard tools, to see how it stacks up in terms of speed, reliability, and ease of use.&lt;/p&gt;
</content:encoded><category>engineering</category><category>mongodb</category><category>cosmos-db</category><category>replication</category><category>benchmarks</category><category>azure</category><author>Alexander Komyagin</author></item><item><title>MongoDB Atlas vs Cosmos DB - A Comparative Guide</title><link>https://www.adiom.io/post/mongodb-atlas-vs-cosmos-db/</link><guid isPermaLink="true">https://www.adiom.io/post/mongodb-atlas-vs-cosmos-db/</guid><description>Introduction to MongoDB Atlas vs Cosmos DBIn the realm of NoSQL databases, MongoDB and Azure Cosmos DB are two powerhouse solutions catering to diverse application needs.</description><pubDate>Mon, 21 Oct 2024 05:06:02 GMT</pubDate><content:encoded>&lt;h2 id=&quot;introduction-to-mongodb-atlas-vs-cosmos-db&quot;&gt;Introduction to MongoDB Atlas vs Cosmos DB&lt;/h2&gt;
&lt;p&gt;In the realm of NoSQL databases, &lt;strong&gt;MongoDB&lt;/strong&gt; and &lt;strong&gt;Azure Cosmos DB&lt;/strong&gt; are two powerhouse solutions catering to diverse application needs. Here are brief overviews and recent developments for each:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;MongoDB&lt;/strong&gt;: The leading document-oriented NoSQL database, MongoDB has just &lt;a href=&quot;https://www.mongodb.com/blog/post/mongodb-8-0-raising-the-bar&quot;&gt;unveiled&lt;/a&gt; &lt;a href=&quot;https://www.mongodb.com/blog/post/mongodb-8-0-raising-the-bar&quot;&gt;&lt;strong&gt;MongoDB 8.0&lt;/strong&gt;&lt;/a&gt;, a landmark release focusing on enhanced performance, security, and scalability. Key highlights include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Improved Query Performance&lt;/strong&gt;: Enhanced query optimization and indexing capabilities.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Client-Side Field Level Encryption (FLE) 2.0&lt;/strong&gt;: Strengthened data protection with more seamless encryption.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Time-Series Data Support&lt;/strong&gt;: Native support for efficient time-series data storage and querying.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Enhanced Aggregation Framework&lt;/strong&gt;: More powerful data processing with improved aggregation capabilities.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Azure Cosmos DB&lt;/strong&gt;: Microsoft’s globally distributed, multi-model database service. Recent updates include the general availability of &lt;strong&gt;vCore provisioning&lt;/strong&gt; for more flexible compute resource allocation, alongside enhancements to its change feed and analytics capabilities.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;1024&quot; src=&quot;/_astro/01.D7iLUiV-_exjPc.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;key-differences-strengths-and-pitfalls&quot;&gt;Key Differences, Strengths, and Pitfalls&lt;/h2&gt;
&lt;h3 id=&quot;mongodb&quot;&gt;MongoDB&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Strengths&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Maturity and wide adoption.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Robust query language and indexing capabilities, &lt;strong&gt;further enhanced in MongoDB 8.0&lt;/strong&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Flexible deployment options (self-managed, MongoDB Atlas).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Native Time-Series Support&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Embedded Vector Search capabilities&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Queryable Encryption&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Pitfalls&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Global distribution and multi-region writes can be somewhat complex to setup and manage unless you’re familiar with sharding.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;May require additional tools for full-stack monitoring and security, though &lt;strong&gt;Client-Side FLE 2.0&lt;/strong&gt; enhances security posture.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;azure-cosmos-db-provisioned-rus-vs-vcore&quot;&gt;Azure Cosmos DB (Provisioned RUs vs vCore)&lt;/h3&gt;
&lt;h4 id=&quot;provisioned-rus-request-units&quot;&gt;Provisioned RUs (Request Units)&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Strengths&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Simplified pricing for predictable workloads.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Works for point queries.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Auto-scaling for throughput (RUs) with Azure Cosmos DB’s autoscale feature.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Comprehensive security and monitoring within Azure.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Pitfalls&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Can be costly for workloads with variable throughput.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Really poor performance for large ingestion or bulk reads.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;No way to develop against it locally.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Over-provisioning to ensure peak performance can lead to wasted resources.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.mongodb.com/resources/compare/mongodb-vs-cosmos-db&quot;&gt;Has notable limitations&lt;/a&gt; when it comes to MongoDB API support, some of them are not well documented (my personal favorite is &lt;a href=&quot;https://www.mongodb.com/docs/manual/reference/operator/aggregation/sample/&quot;&gt;$sample stage&lt;/a&gt; in aggregation not returning uniformly random results)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;vcore-virtual-core-model&quot;&gt;vCore (Virtual Core) Model&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Strengths&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Better suited for compute-intensive, variable workloads.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;More cost-effective for applications with high storage needs but lower throughput demands.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Enhanced flexibility with separate scaling for compute, storage, and I/O.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Pitfalls&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Pricing complexity due to separate billing for compute, storage, and I/O.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Requires more precise resource planning to avoid under/over-provisioning.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Has broader &lt;a href=&quot;https://learn.microsoft.com/en-us/azure/cosmos-db/mongodb/vcore/limits&quot;&gt;functionality limitations&lt;/a&gt; as of now than RU (e.g. ChangeStreams are still &lt;a href=&quot;https://learn.microsoft.com/en-us/azure/cosmos-db/mongodb/vcore/change-streams?tabs=javascript%2CInsert&quot;&gt;not supported&lt;/a&gt;) although the gap is closing quickly.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;5-simple-guidelines-for-choosing-the-right-database-solution&quot;&gt;5 Simple Guidelines for Choosing the Right Database Solution&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Predictable Throughput, Simple Scalability Needs&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Choose MongoDB&lt;/strong&gt; (especially with MongoDB 8.0’s enhancements) if you prefer a self-managed or serverless MongoDB Atlas setup for its straightforward scalability and robust query capabilities.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Opt for Cosmos DB with Provisioned RUs&lt;/strong&gt; if your workload fits well within predictable throughput boundaries and you’re deeply integrated with the Azure ecosystem.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Variable/Compute-Intensive Workloads&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Consider Cosmos DB vCore&lt;/strong&gt; for its flexibility in scaling compute resources independently, ideal for applications with fluctuating demands.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Evaluate MongoDB&lt;/strong&gt; (with its enhanced performance in MongoDB 8.0) if your primary concerns are query complexity and data model flexibility, and you can manage scalability through sharding or third-party tools.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Multi-Region Writes and Conflict Resolution are Key&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Azure Cosmos DB (either RUs or vCore)&lt;/strong&gt; is preferable due to its built-in, customizable conflict resolution mechanisms and seamless global distribution capabilities.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;MongoDB&lt;/strong&gt; may require more application-level logic for conflict resolution, but can still be suitable if your team is experienced with MongoDB’s ecosystem.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Time-Series Data and Enhanced Security are Priorities&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;MongoDB 8.0&lt;/strong&gt; is an attractive choice with its native time-series support and enhanced Client-Side Field Level Encryption (FLE) 2.0 and Queryable Encryption for strengthened data protection.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Ecosystem and Operational Preferences&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Azure Ecosystem&lt;/strong&gt;: If deeply invested in Azure services, Cosmos DB (either provisioning model) integrates seamlessly.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Cross-Cloud or On-Premises Flexibility&lt;/strong&gt;: MongoDB offers more deployment flexibility across various environments.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Choosing Between Azure Cosmos DB’s API for MongoDB vs Native MongoDB Atlas&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Use Azure Cosmos DB’s API for MongoDB&lt;/strong&gt; if:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;You’re already invested in the Azure ecosystem.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Need global distribution with automatic conflict resolution.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Want to leverage Azure’s security and monitoring tools.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Are comfortable with potential feature lag compared to native MongoDB.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Stick with Native MongoDB&lt;/strong&gt; if:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;You prefer more control over database configuration.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Are deeply invested in the MongoDB ecosystem (e.g., MongoDB Atlas, MongoDB Compass).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Require specific MongoDB features not yet supported by Azure Cosmos DB’s API for MongoDB, such as the latest enhancements in &lt;strong&gt;MongoDB 8.0&lt;/strong&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Selecting between MongoDB, Cosmos DB with Provisioned RUs, or Cosmos DB vCore involves weighing your application’s unique needs, scalability patterns, ecosystem preferences, and the latest feature enhancements, such as those introduced in &lt;strong&gt;MongoDB 8.0&lt;/strong&gt;. By understanding the strengths and pitfalls of each, you can make an informed decision that optimizes both performance and cost for your NoSQL database solution.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Next Steps&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Evaluate your application’s specific requirements against the criteria outlined above.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Test and prototype with the chosen database solution to ensure optimal performance and cost alignment.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Stay informed about the latest updates and features from both MongoDB and Azure Cosmos DB to future-proof your database strategy.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;We will be periodically revising our stance and sharing new updates as they come in. Stay tuned!&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If the choice is not obvious for you, no need to worry. Now you have a way to &lt;strong&gt;switch or test out a different solution later on with 0 effort!&lt;/strong&gt; Adiom’s dsync supports online migrations from Cosmos DB to MongoDB Atlas, from MongoDB Atlas to Cosmos DB, and from Cosmos DB with provisioned RUs to Cosmos DB vCore.&lt;/p&gt;
&lt;p&gt;At Adiom, we built &lt;a href=&quot;https://github.com/adiom-data/dsync/&quot;&gt;dsync&lt;/a&gt; to help developers and DevOps perform live migrations and real-time replication easily. Dsync is a fast, reliable, easy-to-use and Open Source solution. Using dsync helps to &lt;strong&gt;accelerate and derisk projects&lt;/strong&gt;, and allows teams to get their applications and services onto a new database in minutes instead of months.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Give dsync a try&lt;/strong&gt; by downloading it from &lt;a href=&quot;https://github.com/adiom-data/dsync/&quot;&gt;GitHub&lt;/a&gt;. It’s distributed as a binary that you can just run anywhere, including your laptop, and it doesn’t require specialized infrastructure or any complex setup.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Adiom offers help and commercial support&lt;/strong&gt; on terms that suit your projects best. Get in touch with us &lt;a href=&quot;https://www.adiom.io/contact&quot;&gt;on the contact page&lt;/a&gt;.&lt;/p&gt;
</content:encoded><category>strategy</category><category>mongodb</category><category>cosmos-db</category><category>vector</category><category>azure</category><author>Alexander Komyagin</author></item><item><title>Migrate from Azure Cosmos DB to MongoDB Atlas Using Dsync</title><link>https://www.adiom.io/post/migrate-from-azure-cosmos-db-to-mongodb-atlas-using-dsync/</link><guid isPermaLink="true">https://www.adiom.io/post/migrate-from-azure-cosmos-db-to-mongodb-atlas-using-dsync/</guid><description>Migrating data between databases can be a complex and time-consuming process, especially for large-scale, mission-critical workloads.</description><pubDate>Tue, 15 Oct 2024 04:46:30 GMT</pubDate><content:encoded>&lt;p&gt;Migrating data between databases can be a complex and time-consuming process, especially for large-scale, mission-critical workloads. One increasingly common scenario is the online or live migration from Azure Cosmos DB to MongoDB Atlas, a high-performance, cloud-native NoSQL database with a wide range of advanced features. This use case presents unique challenges, including compatibility, downtime minimization, and ensuring data consistency throughout the process - see our &lt;a href=&quot;https://www.adiom.io/post/building-a-repeatable-solution-for-cosmos-db-to-mongodb-migration&quot;&gt;previous post&lt;/a&gt; for more details.&lt;/p&gt;
&lt;p&gt;While existing solutions like custom scripts, mongodump/mongorestore, and third-party tools are available, they often fall short in scalability, resiliency, or ease of use. Enter &lt;strong&gt;dsync&lt;/strong&gt;—our open-source tool specifically designed to handle these complex migrations faster and with less risk.&lt;/p&gt;
&lt;h2 id=&quot;dsync-built-to-solve-the-pain-of-data-migration&quot;&gt;Dsync: Built to Solve the Pain of Data Migration&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Dsync&lt;/strong&gt; is a powerful data migration and synchronization tool developed by Adiom, Inc. to address the needs of developers and DevOps teams dealing with large-scale migrations. We built dsync after seeing the limitations of other tools firsthand—either they required too much manual intervention, or they couldn’t scale effectively for production-level workloads. Dsync offers a simple, resilient, and highly performant solution that’s built with both ease of use and enterprise-grade reliability in mind.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key Advantages of Dsync:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Ease of Use&lt;/strong&gt;: Deploy dsync with a single binary—no additional infrastructure required. Run it on VMs or Docker and manage migrations via CLI or web-based monitoring. &lt;em&gt;All complexity of orchestrating a highly parallelized live migration is abstracted away from the user.&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Resiliency&lt;/strong&gt;: Migrations can be interrupted and resumed without losing progress. Dsync ensures data consistency and integrity at every step.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Speed&lt;/strong&gt;: It significantly accelerates migration timelines, reducing hours-long processes to just minutes compared to traditional methods. &lt;em&gt;What could’ve been a 2 hour wait becomes a 10-minute thing.&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Security&lt;/strong&gt;: Dsync doesn’t store data or send it anywhere except the designated destination. It also supports network encryption to keep data secure.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;No Hidden Costs&lt;/strong&gt;: As an &lt;strong&gt;open-source&lt;/strong&gt; tool, dsync eliminates the need to onboard expensive SaaS solutions or purchase licenses in early stages of the process.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt=&quot;Dsync architecture&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;975&quot; height=&quot;666&quot; src=&quot;/_astro/01.DPfCnYJ5_Zul1zW.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;prerequisites-for-migration&quot;&gt;Prerequisites for Migration&lt;/h2&gt;
&lt;p&gt;Before you start migrating from Azure CosmosDB to MongoDB Atlas using dsync, make sure you have the following in place:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Provision the Source (Cosmos DB)&lt;/strong&gt; and &lt;strong&gt;Destination (MongoDB Atlas)&lt;/strong&gt; databases. For optimal performance and to avoid request timeouts, make sure to provision at least 4000 RU/s on your source Cosmos DB collections. On the Atlas side, we recommend M50 or better at least for the migration itself. Dsync supports &lt;a href=&quot;https://docs.adiom.io/basics/features#load-level&quot;&gt;load level configuration&lt;/a&gt; to control how fast it works.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Connection strings&lt;/strong&gt; for both your Cosmos DB and MongoDB Atlas instances, including the necessary credentials and configuration. Don’t worry, dsync doesn’t transfer, store or log your credentials anywhere.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://learn.microsoft.com/en-us/azure/cosmos-db/mongodb/connect-account#get-the-mongodb-connection-string-by-using-the-quick-start&quot;&gt;Instructions for Cosmos DB&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.mongodb.com/docs/guides/atlas/connection-string/&quot;&gt;Instructions for Atlas&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Provision a VM&lt;/strong&gt; for dsync. The most common VM configurations are &lt;em&gt;4 CPUs, 16 GB of RAM&lt;/em&gt; or &lt;em&gt;8 CPUs, 32 GB of RAM.&lt;/em&gt; Ensure that the network is properly configured &lt;em&gt;-&lt;/em&gt; dsync should be able to connect to both the Cosmos DB instance and MongoDB Atlas from that host.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;steps-for-a-live-or-online-migration-using-dsync&quot;&gt;Steps for a Live or Online Migration Using Dsync&lt;/h2&gt;
&lt;p&gt;Once the prerequisites are set, follow these steps to execute your migration seamlessly. You can also find these steps and additional details in our &lt;a href=&quot;https://docs.adiom.io/&quot;&gt;documentation&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;1-download-dsync&quot;&gt;1. Download dsync&lt;/h3&gt;
&lt;p&gt;Head over to the dsync GitHub repository and &lt;strong&gt;download the latest release&lt;/strong&gt;. Unpack the zip and choose the binary that matches your host.&lt;/p&gt;
&lt;h3 id=&quot;2-run-the-migration&quot;&gt;2. Run the Migration&lt;/h3&gt;
&lt;p&gt;Use the CLI to &lt;strong&gt;start your migration&lt;/strong&gt; by providing the necessary connection strings and any configuration settings (such as the databases and collections you want to migrate). Dsync will initiate the transfer of data from your Cosmos DB source to MongoDB Atlas destination.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;./dsync&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -s&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;Cosmo&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;s&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -d&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;Atla&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;s&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --progress&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --logfile&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; dsync.log&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;By default, dsync will use the “adiom-internal” database in your MongoDB Atlas instance to store the metadata, but it’s configurable.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Dsync progress&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;822&quot; height=&quot;223&quot; src=&quot;/_astro/02.rcfQjH-d_Z1LeCSg.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;3-monitor-the-process&quot;&gt;3. Monitor the Process&lt;/h3&gt;
&lt;p&gt;You can &lt;strong&gt;monitor your migration in real-time&lt;/strong&gt; via the web-based interface (accessible via &lt;a href=&quot;http://localhost:8080/progress&quot;&gt;localhost:8080/progress&lt;/a&gt;) or directly in the CLI. Dsync provides detailed logs and metrics on throughput, latency, and any potential errors, allowing you to track progress and troubleshoot as needed.&lt;/p&gt;
&lt;p&gt;After the initial data copy, dsync will automatically switch to CDC-based incremental change replication.&lt;/p&gt;
&lt;p&gt;When the reported replication lag (“Events to catch up”) gets close to 0 and stays there, it means Cosmos DB and Atlas are synchronized.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Dsync progress&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1646&quot; height=&quot;236&quot; src=&quot;/_astro/03.BgQ4YZbN_ZEN0rl.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;You can &lt;strong&gt;initiate the cutover&lt;/strong&gt; by stopping the writes on your source. After that, the lag should go down to 0 quickly. At this point, &lt;strong&gt;the data migration is complete&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;4-validate-the-data&quot;&gt;4. Validate the Data&lt;/h3&gt;
&lt;p&gt;Dsync includes built-in &lt;a href=&quot;https://docs.adiom.io/basics/features#data-integrity-check&quot;&gt;validation mechanisms&lt;/a&gt; to ensure the data is transferred accurately. You can run post-migration checks to verify that all data matches between Cosmos DB and MongoDB Atlas, minimizing the risk of inconsistencies. All you need is to restart the original dsync process and add one new parameter at the end:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;./dsync&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -s&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;Cosmo&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;s&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -d&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;Atla&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;s&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --progress&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --logfile&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; dsync.log&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --verify-quick-count&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;dsync will display the verification result in the CLI.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Dsync progress&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1312&quot; height=&quot;128&quot; src=&quot;/_astro/04.Bty-1JFS_Z1e6Gd7.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;5-cutover&quot;&gt;5. Cutover&lt;/h3&gt;
&lt;p&gt;Once the migration is complete and validated, you can cut over your applications to point to the new MongoDB Atlas database. The switchover can be done with &lt;strong&gt;minimal downtime&lt;/strong&gt;, ensuring a smooth transition without disrupting your business operations.&lt;/p&gt;
&lt;h2 id=&quot;next-steps-unlock-the-power-of-mongodb-atlas&quot;&gt;Next Steps: Unlock the Power of MongoDB Atlas&lt;/h2&gt;
&lt;p&gt;With your data successfully migrated to MongoDB Atlas, you can now leverage its advanced features. MongoDB Atlas offers significant performance improvements with the new &lt;strong&gt;8.0 release&lt;/strong&gt;, including faster queries and enhanced scalability. You can also take advantage of &lt;strong&gt;native vector search&lt;/strong&gt; for AI-driven applications and robust &lt;strong&gt;security features&lt;/strong&gt; for compliance and data protection. Whether you’re scaling globally or improving operational resilience, Atlas provides the tools to make the most of your data.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Migrating from Azure CosmosDB to MongoDB Atlas may seem daunting, but with dsync, the process becomes manageable, resilient, and fast. By following these steps, you can ensure your data is moved with minimal disruption and be ready to unlock the full potential of MongoDB Atlas’s advanced features. If you’re ready to modernize your database infrastructure, &lt;strong&gt;dsync&lt;/strong&gt; is here to help you accelerate the transition and keep your data safe along the way.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;You can see dsync in action in our live demo on&lt;/em&gt; &lt;a href=&quot;https://www.youtube.com/watch?v=r7rAxMTIU-8&quot;&gt;&lt;em&gt;Youtube&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;At Adiom, we built &lt;a href=&quot;https://github.com/adiom-data/dsync/&quot;&gt;dsync&lt;/a&gt; to help developers and DevOps perform live migrations and real-time replication easily. Dsync is a fast, reliable, easy-to-use and Open Source solution. Using dsync helps to &lt;strong&gt;accelerate and derisk projects&lt;/strong&gt;, and allows teams to get their applications and services onto a new database in minutes instead of months.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Give dsync a try&lt;/strong&gt; by downloading it from &lt;a href=&quot;https://github.com/adiom-data/dsync/&quot;&gt;GitHub&lt;/a&gt;. It’s distributed as a binary that you can just run anywhere, including your laptop, and it doesn’t require specialized infrastructure or any complex setup.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Adiom offers help and commercial support&lt;/strong&gt; on terms that suit your projects best. Get in touch with us &lt;a href=&quot;https://www.adiom.io/contact&quot;&gt;on the contact page&lt;/a&gt;.&lt;/p&gt;
</content:encoded><category>guides</category><category>mongodb</category><category>cosmos-db</category><category>azure</category><author>Alexander Komyagin</author></item><item><title>A Repeatable Solution for Cosmos DB to MongoDB Migration</title><link>https://www.adiom.io/post/building-a-repeatable-solution-for-cosmos-db-to-mongodb-migration/</link><guid isPermaLink="true">https://www.adiom.io/post/building-a-repeatable-solution-for-cosmos-db-to-mongodb-migration/</guid><description>This is an updated version of the original article published on Medium by our CEO, Alexander Komyagin.</description><pubDate>Mon, 14 Oct 2024 02:59:13 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;686&quot; height=&quot;220&quot; src=&quot;/_astro/01.BbSi5tmJ_28WJza.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;This is an updated version of the &lt;a href=&quot;https://medium.com/@adkomyagin/building-a-repeatable-solution-for-cosmos-db-to-mongodb-migration-in-house-121c6edfcdec&quot;&gt;original article&lt;/a&gt; published on Medium by our CEO, Alexander Komyagin. In this article we’ll explore the challenges of building a solution for &lt;strong&gt;live migration&lt;/strong&gt; from Cosmos DB to MongoDB. There are many reasons for users to want to migrate - we will save them for a future article. Here we will focus on technical challenges of what might look like an easy migration between two databases with the same API.&lt;/p&gt;
&lt;h2 id=&quot;the-reality-of-compatibility&quot;&gt;The Reality of Compatibility&lt;/h2&gt;
&lt;p&gt;Cosmos DB for MongoDB is compatible with a &lt;strong&gt;limited subset&lt;/strong&gt; of MongoDB’s wire protocol, suitable only for the &lt;strong&gt;simplest MongoDB applications&lt;/strong&gt;. This limited compatibility can lead to higher costs and unexpected challenges. Standard MongoDB migration tools (mongomirror, mongosync, etc.) don’t work. Mongodump and mongorestore turn out to be painfully slow and can take hours on a relatively small (&amp;lt;100GB) dataset.&lt;/p&gt;
&lt;h2 id=&quot;key-concerns-for-migration&quot;&gt;Key Concerns for Migration&lt;/h2&gt;
&lt;p&gt;Migrating production workloads involves addressing several critical concerns:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Avoiding Excessive Downtime&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Speeding Up the Migration&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Preserving Data Integrity&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Implementing a Rollback Plan&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;avoiding-downtime&quot;&gt;Avoiding Downtime&lt;/h2&gt;
&lt;p&gt;For larger datasets, avoiding downtime during migration is crucial. A live migration approach typically involves the following stages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Initial Data Copy:&lt;/strong&gt; Bulk copy the data from the source to the destination.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Capturing Changes&lt;/strong&gt;: Use Change Data Capture (CDC) to capture changes from the beginning of the data copy process and apply them after the copy is done.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Replicating Changes&lt;/strong&gt;: Continue replicating changes until the lag between the destination and the source is small enough to cut over.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1590&quot; height=&quot;515&quot; src=&quot;/_astro/02.lav7taBK_1y2Eq.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;However, Cosmos DB’s limited support for Change Streams complicates the approach:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;No Delete Events&lt;/strong&gt;: It’s recommended that users implement safe-deletes in their applications using a special field to mark deleted documents and set the TTL field for automatic cleanup. They will need to clean up those documents on the MongoDB side as well. In any case, users &lt;strong&gt;will&lt;/strong&gt; likely need to change their application to make it all work. In certain cases, it’s possible to compare the source and destination collections side-by-side to determine what was deleted - that’s the approach we implemented in Adiom’s &lt;a href=&quot;https://github.com/adiom-data/dsync/&quot;&gt;dsync&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Per-Collection Change Streams&lt;/strong&gt;: There’s no global or per-database Change Stream support. Each collection needs to have its own Change Stream, requiring writing scripts or coordinating parallel Change Streams. In our tests, we saw performance degradation with more than 10–15 parallel Change Streams on Cosmos DB.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Specific Pipeline Options&lt;/strong&gt;: Cosmos DB requires using the exact Change Stream pipeline &lt;a href=&quot;https://learn.microsoft.com/en-us/azure/cosmos-db/mongodb/change-streams?tabs=javascript&quot;&gt;options&lt;/a&gt; as specified; otherwise, it won’t work. They also always return the full document, so a replace is needed on the destination. This creates serious risks for gradual cutovers where writes on the destination are allowed early assuming no conflicts. To mitigate these risks, a reliable way to check &lt;a href=&quot;https://docs.adiom.io/basics/features#data-integrity-check&quot;&gt;data integrity&lt;/a&gt; is required.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;No Timestamps&lt;/strong&gt;: Timestamps are normally used to calculate the replication lag or delay. Knowing the lag is extremely important to properly time the cutover in live migrations. Since Cosmos DB Change Stream events don’t have timestamps, a different method is required. In Adiom’s &lt;a href=&quot;https://github.com/adiom-data/dsync/&quot;&gt;dsync&lt;/a&gt; we use event sequencing to calculate the lag.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Lastly, it’s important to ensure proper coordination between Change Streams and initial data copy to avoid data loss due to race conditions. In Adiom’s &lt;a href=&quot;https://github.com/adiom-data/dsync/&quot;&gt;dsync&lt;/a&gt;, this is done automatically behind the scenes, without requiring any input from the user.&lt;/p&gt;
&lt;h2 id=&quot;speeding-up-the-migration&quot;&gt;Speeding Up the Migration&lt;/h2&gt;
&lt;p&gt;Migration speed depends on:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Latency&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Level of Parallelization&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Provisioned RU/s on the source&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Capacity on the destination (CPU, RAM, disk IO)&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Network latency to Cosmos DB can significantly impact throughput. In &lt;a href=&quot;https://github.com/adiom-data/dsync/&quot;&gt;dsync&lt;/a&gt;, we parallelize reads from different namespaces. Further, we employ intelligent partitioning strategies to identify sensible split point(s) in the range of _id values, and use parallel range queries for large namespaces to increase speed. Sadly, Cosmos DB’s implementation of the aggregation $sample command &lt;a href=&quot;https://github.com/MicrosoftDocs/azure-docs/issues/10382#issuecomment-403916154&quot;&gt;does&lt;/a&gt; &lt;a href=&quot;https://github.com/MicrosoftDocs/azure-docs/issues/10382#issuecomment-403916154&quot;&gt;&lt;strong&gt;not&lt;/strong&gt;&lt;/a&gt; work correctly, so we can’t do statistical sampling to determine split points programmatically.&lt;/p&gt;
&lt;h2 id=&quot;resumability&quot;&gt;Resumability&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/adiom-data/dsync/&quot;&gt;Dsync&lt;/a&gt; tracks synced namespaces and stores resume tokens from Change Streams to avoid restarting the migration process from scratch. This is particularly important during the initial testing phase but also for ensuring reliability.&lt;/p&gt;
&lt;h2 id=&quot;data-integrity&quot;&gt;Data Integrity&lt;/h2&gt;
&lt;p&gt;With no &lt;a href=&quot;https://www.mongodb.com/docs/manual/reference/command/dbHash/&quot;&gt;dbHash&lt;/a&gt; support in Cosmos DB, &lt;a href=&quot;https://github.com/adiom-data/dsync/&quot;&gt;dsync&lt;/a&gt; relies on heuristics like count and size, as well as comprehensive per-namespace checksum comparison.&lt;/p&gt;
&lt;h2 id=&quot;backout-plan&quot;&gt;Backout Plan&lt;/h2&gt;
&lt;p&gt;In Enterprise and mission-critical applications it’s more than just a checkbox item. Having an out-of-the-box ability to reverse the synchronization process helps to accelerate planning and testing.&lt;/p&gt;
&lt;h2 id=&quot;observability&quot;&gt;Observability&lt;/h2&gt;
&lt;p&gt;It’s important to expose and monitor metrics to identify bottlenecks and ensure direct visibility into the migration process. Bottlenecks can differ between clusters, environments, and sometimes between runs. &lt;a href=&quot;https://github.com/adiom-data/dsync/&quot;&gt;Dsync&lt;/a&gt; offers a CLI- and Web-based progress output, and detailed logs.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Migrating from Cosmos DB to MongoDB is challenging but manageable with the right approach. Addressing key concerns around downtime, speed, data integrity, and backout plans ensures a smooth transition.&lt;/p&gt;
&lt;p&gt;At Adiom, we built &lt;a href=&quot;https://github.com/adiom-data/dsync/&quot;&gt;dsync&lt;/a&gt; to help developers and DevOps perform live migrations and real-time replication easily. Dsync is a fast, reliable, easy-to-use and Open Source solution. Using dsync helps to &lt;strong&gt;accelerate and derisk projects&lt;/strong&gt;, and allows teams to get their applications and services onto a new database in minutes instead of months.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Give dsync a try&lt;/strong&gt; by downloading it from &lt;a href=&quot;https://github.com/adiom-data/dsync/&quot;&gt;GitHub&lt;/a&gt;. It’s distributed as a binary that you can just run anywhere, including your laptop, and it doesn’t require specialized infrastructure or any complex setup.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Adiom offers help and commercial support&lt;/strong&gt; on terms that suit your projects best. Get in touch with us &lt;a href=&quot;https://www.adiom.io/contact&quot;&gt;on the contact page&lt;/a&gt;.&lt;/p&gt;
</content:encoded><category>guides</category><category>mongodb</category><category>cosmos-db</category><category>replication</category><author>Alexander Komyagin</author></item><item><title>Powering Universal Data Exchange with Adiom</title><link>https://www.adiom.io/post/powering-universal-data-exchange-with-adiom-software/</link><guid isPermaLink="true">https://www.adiom.io/post/powering-universal-data-exchange-with-adiom-software/</guid><description>In today&apos;s data-driven world, the need for seamless data exchange and synchronization between Enterprise databases and Edge devices is more crucial than ever.</description><pubDate>Tue, 08 Oct 2024 19:36:48 GMT</pubDate><content:encoded>&lt;p&gt;In today’s data-driven world, the need for seamless data exchange and synchronization between Enterprise databases and Edge devices is more crucial than ever. This is where Adiom comes into play, providing innovative solutions to bridge the gap between large heterogeneous databases and the Edge, making data mobility easier and more efficient.&lt;/p&gt;
&lt;p&gt;Adiom’s vision of establishing a universal data fabric for data object-based communication, management, and exchange is truly groundbreaking. By offering data synchronization tools that are simple, fast, reliable, and Open Source, the company is setting a new standard in the industry.&lt;/p&gt;
&lt;p&gt;With a focus on expanding its customer base and enhancing user experience, Adiom’s website serves as a platform to showcase the company’s cutting-edge features and functionalities. While the business history is currently undisclosed, the emphasis remains on driving innovation in data mobility. By leveraging Adiom, Enterprises can streamline their data exchange processes and optimize communication between different systems. Whether it’s syncing data between Enterprise databases or facilitating real-time interactions at the Edge, Adiom’s solutions empower organizations to stay ahead in today’s competitive landscape.&lt;/p&gt;
&lt;p&gt;In conclusion, Adiom is at the forefront of revolutionizing data mobility, making it easier for businesses to exchange and manage data effectively. With a commitment to simplicity, speed, reliability, and Open Source principles, Adiom is paving the way for a more connected and data-driven future.&lt;/p&gt;
</content:encoded><category>product</category><author>Alexander Komyagin</author></item><item><title>Simplify Enterprise Database Communication with Adiom</title><link>https://www.adiom.io/post/simplify-enterprise-database-communication-with-adiom-solutions/</link><guid isPermaLink="true">https://www.adiom.io/post/simplify-enterprise-database-communication-with-adiom-solutions/</guid><description>In the fast-paced world of Enterprise database communication, efficiency is key. Adiom Solutions, a leading tech company, is on a mission to simplify data mobility for businesses dealing with large and critical databases.</description><pubDate>Tue, 08 Oct 2024 19:36:48 GMT</pubDate><content:encoded>&lt;p&gt;In the fast-paced world of Enterprise database communication, efficiency is key. Adiom Solutions, a leading tech company, is on a mission to simplify data mobility for businesses dealing with large and critical databases. With a vision to enable seamless data exchange between Enterprise databases and the Edge, Adiom is revolutionizing the way data is managed and communicated.&lt;/p&gt;
&lt;p&gt;At the core of Adiom’s offerings are their data synchronization tools, designed to be the simplest, fastest, most reliable, and Open Source. These tools empower businesses to streamline their database communication processes, ultimately enhancing productivity and efficiency. Whether it’s syncing data between databases, managing data objects, or facilitating communication between different systems, Adiom’s solutions are tailored to meet the needs of modern enterprises.&lt;/p&gt;
&lt;p&gt;One of the key highlights of Adiom’s approach is its emphasis on user experience and customer satisfaction. By providing intuitive tools and resources, Adiom aims to improve the overall experience for its users and expand its customer base. Adiom’s focus on innovation and simplicity speaks volumes about its commitment to driving progress in the tech industry. By offering Open Source solutions and prioritizing user experience, Adiom is setting itself apart as a leader in the field of Enterprise database communication. In a world where data is king, Adiom is paving the way for a more connected and efficient future. With their cutting-edge tools and commitment to simplicity, businesses can trust Adiom to simplify their database communication processes and streamline their operations.&lt;/p&gt;
</content:encoded><category>product</category><author>Alexander Komyagin</author></item></channel></rss>