mongodb
mariadb

Migrate MongoDB to MariaDB

Beta — live-tested path

Migrating from MongoDB (the leading document database) to MariaDB (the community-driven MySQL fork) means every table, column type, key, index and row has to survive two engines' different opinions about data. This is a cross-model migration — documents become relational rows with an inferred schema — and the conversion rules are explicit, not guessed. DBShifts converts the schema with deterministic rules, transfers data in parallel batches, and validates the result with per-table row counts and type-aware checksums.

Start MongoDBMariaDB Migration

Free tier · no credit card

MongoDB vs MariaDB

mongodb

MongoDB

the leading document database.

mariadb

MariaDB

the community-driven MySQL fork.

How the migration works

01

Connect

Point DBShifts at your source and target. Credentials stay encrypted; SSH tunnels supported for private databases.

02

Analyze

Automatic schema introspection produces a migration plan: what converts automatically, what migrates with warnings, what needs human review.

03

Migrate

Schema is created on the target, data transfers in parallel batches with constraints deferred, indexes rebuilt after load.

04

Validate

Per-table row counts, type-aware checksums on both sides, FK integrity — plus a fidelity report listing anything lossy.

MongoDB to MariaDB data type mapping

Pulled directly from DBShifts's own conversion rules — not a general reference table, this is what actually runs.

MongoDBMariaDB
ObjectIdvarchar(24)
String (up to 255 chars)varchar(255)
String (longer)text
Int32int
Int64bigint
Doubledouble
Decimal128decimal(38,9)
Booleantinyint(1)
Datedatetime
Timestamptimestamp
Binaryblob
Arrayjson
Object / subdocumentjson
UUIDvarchar(36)
Nulltext

Example: MongoDB to MariaDB conversion

MongoDB

// one document from the "orders" collection
{
  "_id":         ObjectId("6512c3a1f4b2e9d0a7c1b234"),
  "customer_id": NumberLong(4821),
  "total":       NumberDecimal("129.99"),
  "is_gift":     false,
  "notes":       "leave at reception",
  "tags":        ["priority", "fragile"],
  "placed_at":   ISODate("2026-03-14T09:20:00Z")
}

MariaDB

CREATE TABLE IF NOT EXISTS `orders` (
    `_id` varchar(24),
    `customer_id` bigint NOT NULL,
    `total` decimal(38,9) NOT NULL,
    `is_gift` tinyint(1),
    `notes` varchar(255),
    `tags` json,
    `placed_at` datetime NOT NULL,
    PRIMARY KEY (`_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

Inferring a schema from documents that have none

MongoDB collections have no declared schema, so the target columns have to be inferred by sampling documents. That works well when documents are consistent and badly when they are not: a field present in 2% of documents may not appear in the sample at all, and a field holding a string in some documents and a number in others has no single correct column type.

The conservative resolution is to widen. A field seen as both integer and string becomes text, which keeps every value at the cost of type precision. It is worth reviewing the inferred schema before the load rather than after, because a widened column is easy to narrow while the table is empty and expensive to change later.

Nested documents and arrays have no column equivalent

A nested object becomes a JSON column rather than being split into separate columns, and an array becomes a JSON column rather than a child table. Both are defensible defaults, and both mean the data is no longer queryable the way a relational schema would allow: you cannot index an array element as a column or join to it.

Where an array genuinely represents a one-to-many relationship, converting it to a child table is the better long-term shape and requires a modelling decision that no automatic conversion should make silently. Doing the faithful JSON copy first and normalising afterwards keeps both options open.

MariaDB stores JSON as LONGTEXT with validation rather than as a distinct binary type, so JSON functions work but the storage and indexing characteristics differ from a native JSON type.

_id and the primary key

Every document has an _id, and by default it is a 12-byte ObjectId rendered as 24 hexadecimal characters. That becomes a VARCHAR(24) primary key, which works and is larger and less efficient than an integer key for both storage and index size.

If the collection has a natural key already, using it as the primary key and keeping _id as an ordinary indexed column usually produces a better relational schema. ObjectIds also encode their creation time in the leading bytes, so a created_at column can be derived from them where none was stored explicitly.

MongoDBMariaDB conversion notes

Engine-specific rules baked into the conversion and transfer pipeline — verified by live certification of this exact pair.

  • Schema is inferred by sampling documents — null values don't poison type inference (a nullable int stays an int column).
  • Decimal128 maps to exact DECIMAL on SQL targets, never a float round-trip.
  • Nested documents and arrays land as JSON/JSONB columns with data preserved byte-for-byte.
  • _id becomes the primary key; ObjectId converts to its 24-character hex form.
  • Literal 'NULL' defaults reported by MariaDB's information schema are cleaned instead of becoming DEFAULT 'NULL' strings.
  • AUTO_INCREMENT reseed after bulk load, same as MySQL.

Frequently asked questions

Is MongoDB to MariaDB migration production-ready in DBShifts?

MongoDB to MariaDB is a live-verified beta pair: it passed the same certification suite as every other pair — a real migration with edge-case data validated by row counts and checksums — and ships with a post-migration fidelity report you can audit before cutover.

How does DBShifts verify the MongoDB to MariaDB migration was correct?

Three layers: per-table row counts on both sides, an order-independent type-aware checksum of row data (canonicalized so engine representation differences don't false-alarm), and FK integrity checks on the target. Rows that fail to insert are quarantined with the exact error — never silently dropped — and can be fixed and retried from the UI.

What happens to MongoDB types that MariaDB doesn't have?

They convert by deterministic rules with a recorded decision: a native equivalent where one exists, a portable fallback (TEXT/JSON/DECIMAL) where one doesn't. Every lossy conversion appears in the migration plan before you run and in the fidelity report after. You can override any mapping per column.

Can I keep MongoDB and MariaDB in sync after the initial migration?

Yes. DBShifts supports incremental sync (UPSERT-based delta transfers on a sync key) and, for supported sources, real-time change data capture so the target stays current until you cut over.

Do I need to write any SQL or scripts for MongoDB to MariaDB?

No. Connect both databases, review the generated migration plan (what's automatic, what migrates with warnings, what needs manual review — typically triggers and stored procedures), and run. Procedural code is transpiled best-effort and queued for human review rather than auto-applied.

What's the hardest part of moving MongoDB to MariaDB?

The data model itself differs (nosql → sql), so a relational schema is inferred from documents and nested data lands as JSON columns. DBShifts surfaces every inference and lossy conversion in the migration plan before you run, so nothing is guessed silently.

Which MongoDB data types change when moving to MariaDB?

5 of the mapped types convert to something that cannot represent exactly the same range or constraint. The clearest cases are ObjectId to varchar(24), Decimal128 to decimal(38,9), Array to json. The full table above lists every mapping the converter performs, and analysis flags each one on your actual schema before any data moves.

Go deeper

Related migration paths

Ready to move MongoDB to MariaDB?

Set up in under two minutes. Validation and rollback included.

Start Free Migration