The DocumentDB extension, providing MongoDB compatibility for PostgreSQL, is available in preview in YugabyteDB 2026.1, with some limitations, such as the absence of secondary indexes and lack of support for ARM processors. Still, it's interesting to see how it works.
I've launched a Docker container from the image containing version 2026.1.0.0, build 118:
docker run --rm -it -p 27017:27017 -p 15433:15433 \
yugabytedb/yugabyte:latest bash
I started one node, setting the necessary flags:
yugabyted start \
--master_flags="allowed_preview_flags_csv=ysql_enable_documentdb,ysql_enable_documentdb=true,enable_pg_cron=true" \
--tserver_flags="allowed_preview_flags_csv=ysql_enable_documentdb,ysql_enable_documentdb=true,enable_pg_cron=true" \
--ui=true
The DocumentDB offers a MongoDB-compatible endpoint; however, to observe the internals, I used the PostgreSQL client:
ysqlsh -h $HOSTNAME
From the PostgreSQL client, I used the DocumentDB API to run MongoDB-compatible commands from SQL. I imported a collection with ten thousand documents, each including a nested array of one hundred items:
create extension if not exists documentdb cascade;
select documentdb_api.drop_collection ('db','coll1');
select documentdb_api.create_collection ('db','coll1');
with docs(document) as (select
json_build_object(
'_id', n,
'field1', n%100,
'field2', md5(random()::text),
'field3', md5(random()::text),
'field4', md5(random()::text),
'field5', md5(random()::text),
'array', (
select json_agg(child.id+ case when n%3=0 then 0 else random() end)
from generate_series(1, 1e2) AS child(id)
)
) from generate_series(1, 1e5) n
)
select count(documentdb_api.insert_one ('db','coll1',
document::text::documentdb_core.bson
)) from docs;
;
I check a sample of data:
set documentdb_core.bsonUseEJson to true;
\pset pager off
select document from documentdb_api_catalog.bson_aggregation_pipeline(
'db', '{"aggregate": "coll1", "pipeline": [
{"$limit": 2 }
], "cursor": {}}'::documentdb_core.bson
);
Result:
document
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
{ "_id" : { "$numberInt" : "78047" }, "field1" : { "$numberInt" : "47" }, "field2" : "61160c5889651c7aeb9b53c9e8c16874", "field3" : "a5643ebcf7b4cb52ce5606347a48159d", "field4" : "1920dadda82764003c8666396927d184", "field5" : "38981fb4fe2874a16e71adb91eaf80b7", "array" : [ { "$numberDouble" : "1.6680338007661099642" }, { "$numberDouble" : "2.0321660675583723688" }, { "$numberDouble" : "3.7248612825324078912" }, { "$numberDouble" : "4.6682151188376419526" }, { "$numberDouble" : "5.352836859518445678" }, { "$numberDouble" : "6.1549238121424405534" }, { "$numberDouble" : "7.5698744025959001647" }, { "$numberDouble" : "8.3627292359089526741" }, { "$numberDouble" : "9.7284070730559299989" }, { "$numberDouble" : "10.648505386329139455" }, { "$numberDouble" : "11.819375264988172702" }, { "$numberDouble" : "12.564692810410857504" }, { "$numberDouble" : "13.578234292227129743" }, { "$numberDouble" : "14.840940698922509" }, { "$numberDouble" : "15.000110832002331307" }, { "$numberDouble" : "16.358619841052682631" }, { "$numberDouble" : "17.114466577365092803" }, { "$numberDouble" : "18.453576775946736177" }, { "$numberDouble" : "19.612164960288463789" }, { "$numberDouble" : "20.763510570791428478" }, { "$numberDouble" : "21.072906780595499043" }, { "$numberDouble" : "22.302558940939842813" }, { "$numberDouble" : "23.028762426311956801" }, { "$numberDouble" : "24.977457545570718622" }, { "$numberDouble" : "25.168495224042882086" }, { "$numberDouble" : "26.683268805530829582" }, { "$numberDouble" : "27.603359814890115587" }, { "$numberDouble" : "28.878206328994565411" }, { "$numberDouble" : "29.721073180897786159" }, { "$numberDouble" : "30.626948384420241922" }, { "$numberDouble" : "31.671570586699115069" }, { "$numberDouble" : "32.662353414214038594" }, { "$numberDouble" : "33.46460769319755002" }, { "$numberDouble" : "34.940574677532538317" }, { "$numberDouble" : "35.970141769064831294" }, { "$numberDouble" : "36.179330236215683669" }, { "$numberDouble" : "37.600489143561993899" }, { "$numberDouble" : "38.84836254286827284" }, { "$numberDouble" : "39.212520619284028101" }, { "$numberDouble" : "40.552350139480068947" }, { "$numberDouble" : "41.534399323092017653" }, { "$numberDouble" : "42.675192781144495768" }, { "$numberDouble" : "43.897435440034712428" }, { "$numberDouble" : "44.643362479639151275" }, { "$numberDouble" : "45.079069764447424973" }, { "$numberDouble" : "46.571893792280704361" }, { "$numberDouble" : "47.247632193766989417" }, { "$numberDouble" : "48.490043046330811194" }, { "$numberDouble" : "49.453768298556425975" }, { "$numberDouble" : "50.918392174574123032" }, { "$numberDouble" : "51.920252310666860751" }, { "$numberDouble" : "52.939591943997093892" }, { "$numberDouble" : "53.620526333881137759" }, { "$numberDouble" : "54.692199233976516837" }, { "$numberDouble" : "55.398818854086997021" }, { "$numberDouble" : "56.650202658333142836" }, { "$numberDouble" : "57.70283083519552747" }, { "$numberDouble" : "58.48719280187031444" }, { "$numberDouble" : "59.932029859433328056" }, { "$numberDouble" : "60.435350057667704959" }, { "$numberDouble" : "61.796201961995798513" }, { "$numberDouble" : "62.883084798688862804" }, { "$numberDouble" : "63.070790792109328038" }, { "$numberDouble" : "64.16759516733826274" }, { "$numberDouble" : "65.684735624962627298" }, { "$numberDouble" : "66.406523484084644338" }, { "$numberDouble" : "67.628489973539217317" }, { "$numberDouble" : "68.548155362022797021" }, { "$numberDouble" : "69.446152335761937024" }, { "$numberDouble" : "70.850816173934148878" }, { "$numberDouble" : "71.371987666701940611" }, { "$numberDouble" : "72.231763790086574772" }, { "$numberDouble" : "73.057257769223340915" }, { "$numberDouble" : "74.248606955094231807" }, { "$numberDouble" : "75.734788957354354011" }, { "$numberDouble" : "76.261763568307117112" }, { "$numberDouble" : "77.366290387804127704" }, { "$numberDouble" : "78.090952646323614772" }, { "$numberDouble" : "79.907761062715451317" }, { "$numberDouble" : "80.213292529749651294" }, { "$numberDouble" : "81.40122970782175571" }, { "$numberDouble" : "82.397874716128853834" }, { "$numberDouble" : "83.856288865693912271" }, { "$numberDouble" : "84.836437448365771274" }, { "$numberDouble" : "85.712489576106221989" }, { "$numberDouble" : "86.344972416913108759" }, { "$numberDouble" : "87.838719804924522805" }, { "$numberDouble" : "88.736218332587981195" }, { "$numberDouble" : "89.061374463030290372" }, { "$numberDouble" : "90.181943740431705692" }, { "$numberDouble" : "91.370555458410805727" }, { "$numberDouble" : "92.540259312764803212" }, { "$numberDouble" : "93.151492898837148005" }, { "$numberDouble" : "94.45972723544899452" }, { "$numberDouble" : "95.041905493739093913" }, { "$numberDouble" : "96.099361464158789659" }, { "$numberDouble" : "97.057660017948322206" }, { "$numberDouble" : "98.420677137980504767" }, { "$numberDouble" : "99.694426199374930775" }, { "$numberDouble" : "100.28095505763631934" } ] }
{ "_id" : { "$numberInt" : "84564" }, "field1" : { "$numberInt" : "64" }, "field2" : "e14fc6847516bbae0055d5e29a8331db", "field3" : "0d91f561a9af719b173283826fff7dc9", "field4" : "7c7009c2b6b2d63ada1f3c84ee9e55dc", "field5" : "43d6dbdb0613c6ed6979b797fd693c9a", "array" : [ { "$numberInt" : "1" }, { "$numberInt" : "2" }, { "$numberInt" : "3" }, { "$numberInt" : "4" }, { "$numberInt" : "5" }, { "$numberInt" : "6" }, { "$numberInt" : "7" }, { "$numberInt" : "8" }, { "$numberInt" : "9" }, { "$numberInt" : "10" }, { "$numberInt" : "11" }, { "$numberInt" : "12" }, { "$numberInt" : "13" }, { "$numberInt" : "14" }, { "$numberInt" : "15" }, { "$numberInt" : "16" }, { "$numberInt" : "17" }, { "$numberInt" : "18" }, { "$numberInt" : "19" }, { "$numberInt" : "20" }, { "$numberInt" : "21" }, { "$numberInt" : "22" }, { "$numberInt" : "23" }, { "$numberInt" : "24" }, { "$numberInt" : "25" }, { "$numberInt" : "26" }, { "$numberInt" : "27" }, { "$numberInt" : "28" }, { "$numberInt" : "29" }, { "$numberInt" : "30" }, { "$numberInt" : "31" }, { "$numberInt" : "32" }, { "$numberInt" : "33" }, { "$numberInt" : "34" }, { "$numberInt" : "35" }, { "$numberInt" : "36" }, { "$numberInt" : "37" }, { "$numberInt" : "38" }, { "$numberInt" : "39" }, { "$numberInt" : "40" }, { "$numberInt" : "41" }, { "$numberInt" : "42" }, { "$numberInt" : "43" }, { "$numberInt" : "44" }, { "$numberInt" : "45" }, { "$numberInt" : "46" }, { "$numberInt" : "47" }, { "$numberInt" : "48" }, { "$numberInt" : "49" }, { "$numberInt" : "50" }, { "$numberInt" : "51" }, { "$numberInt" : "52" }, { "$numberInt" : "53" }, { "$numberInt" : "54" }, { "$numberInt" : "55" }, { "$numberInt" : "56" }, { "$numberInt" : "57" }, { "$numberInt" : "58" }, { "$numberInt" : "59" }, { "$numberInt" : "60" }, { "$numberInt" : "61" }, { "$numberInt" : "62" }, { "$numberInt" : "63" }, { "$numberInt" : "64" }, { "$numberInt" : "65" }, { "$numberInt" : "66" }, { "$numberInt" : "67" }, { "$numberInt" : "68" }, { "$numberInt" : "69" }, { "$numberInt" : "70" }, { "$numberInt" : "71" }, { "$numberInt" : "72" }, { "$numberInt" : "73" }, { "$numberInt" : "74" }, { "$numberInt" : "75" }, { "$numberInt" : "76" }, { "$numberInt" : "77" }, { "$numberInt" : "78" }, { "$numberInt" : "79" }, { "$numberInt" : "80" }, { "$numberInt" : "81" }, { "$numberInt" : "82" }, { "$numberInt" : "83" }, { "$numberInt" : "84" }, { "$numberInt" : "85" }, { "$numberInt" : "86" }, { "$numberInt" : "87" }, { "$numberInt" : "88" }, { "$numberInt" : "89" }, { "$numberInt" : "90" }, { "$numberInt" : "91" }, { "$numberInt" : "92" }, { "$numberInt" : "93" }, { "$numberInt" : "94" }, { "$numberInt" : "95" }, { "$numberInt" : "96" }, { "$numberInt" : "97" }, { "$numberInt" : "98" }, { "$numberInt" : "99" }, { "$numberInt" : "100" } ] }
(2 rows)
yugabyte=#
To look at the internals, I need the name of the PostgreSQL table that stores the "db.coll1" collection:
-- get the internal table name
select format('documentdb_data.documents_%s',collection_id) as tab
from documentdb_api_catalog.collections
where (database_name,collection_name) = ('db','coll1')
\gset
\d :tab
Result:
yugabyte-# \gset
yugabyte=# \d :tab
Table "documentdb_data.documents_2"
Column | Type | Collation | Nullable | Default
-----------------+----------------------+-----------+----------+---------
shard_key_value | bigint | | not null |
object_id | documentdb_core.bson | | not null |
document | documentdb_core.bson | | not null |
Indexes:
"collection_pk_2" PRIMARY KEY, lsm ((shard_key_value, object_id) HASH)
Check constraints:
"shard_key_value_check" CHECK (shard_key_value = '2'::bigint)
yugabyte=#
There's a single index on the "object_id" (which is the "_id"). In PostgreSQL, it is a B-tree. In YugabyteDB, it is an LSM tree.
I check the tablets
select tablet_id, table_name, state, partition_key_start, partition_key_end
from yb_local_tablets
where ysql_schema_name||'.'||table_name = :'tab';
\gset
\setenv tablet_id :tablet_id
\! /home/yugabyte/bin/yb-admin --master_addresses $HOSTNAME:7100 list_tablet_servers $tablet_id
Result:
yugabyte=# \gset
yugabyte=# \setenv tablet_id :tablet_id
yugabyte=# \! /home/yugabyte/bin/yb-admin --master_addresses $HOSTNAME:7100 list_tablet_servers $tablet_id
Server UUID RPC Host/Port Role
65fa009d2c15448db385b1abf46e1e97 3e439d75380b:9100 LEADER
yugabyte=#
This is also visible from the UI on http://localhost:15433/databases/tabYsql
Here is the execution plan for a query by "_id":
yugabyte=# explain (costs off, analyze on, dist on, debug on, verbose on, summary off)
select document from documentdb_api_catalog.bson_aggregation_pipeline(
'db', '{"aggregate": "coll1", "pipeline": [
{"$match": { "_id": 42 , "array": 42 } }
], "cursor": {}}'::documentdb_core.bson
);
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Index Scan using collection_pk_2 on documentdb_data.documents_2 collection (actual time=0.805..0.808 rows=1 loops=1)
Output: document
Index Cond: ((collection.shard_key_value = '2'::bigint) AND (collection.object_id OPERATOR(documentdb_core.=) '{ "" : { "$numberInt" : "42" } }'::documentdb_core.bson))
Filter: ((collection.document OPERATOR(documentdb_api_catalog.@=) '{ "_id" : { "$numberInt" : "42" } }'::documentdb_core.bson) AND (collection.document OPERATOR(documentdb_api_catalog.@=) '{ "array" : { "$numberInt" : "42" } }'::documentdb_core.bson))
Storage Table Read Requests: 1
Storage Table Read Execution Time: 0.605 ms
Storage Table Read Ops: 1
Storage Table Rows Scanned: 1
Metric rocksdb_block_cache_hit: 5.000
Metric rocksdb_block_cache_index_hit: 1.000
Metric rocksdb_block_cache_filter_hit: 1.000
Metric rocksdb_block_cache_data_hit: 1.000
Metric rocksdb_bloom_filter_useful: 1.000
Metric rocksdb_bloom_filter_checked: 2.000
Metric rocksdb_number_db_seek: 1.000
Metric rocksdb_number_db_next: 1.000
Metric rocksdb_number_db_seek_found: 1.000
Metric rocksdb_number_db_next_found: 1.000
Metric rocksdb_iter_bytes_read: 2561.000
Metric rocksdb_block_cache_multi_touch_hit: 5.000
Metric docdb_keys_found: 1.000
Metric ql_read_latency: sum: 98.000, count: 1.000
Estimated Seeks: 1
Estimated Nexts And Prevs: 1001
Estimated Table Roundtrips: 0
Estimated Index Roundtrips: 1
Estimated Docdb Result Width: 1285
(27 rows)
yugabyte=#
This is an optimal plan with a single read request to the tablet determined by the hash value of (shard_key_value, object_id), and a single "seek" in the LSM tree to get the row with one "next".
Because secondary indexes are not supported yet, it is different if I query by another field:
yugabyte=# explain (costs off, analyze on, dist on, debug on, verbose on, summary off)
select document from documentdb_api_catalog.bson_aggregation_pipeline(
'db', '{"aggregate": "coll1", "pipeline": [
{"$match": { "field1": 42 , "array": 42 } }
], "cursor": {}}'::documentdb_core.bson
);
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Index Scan using collection_pk_2 on documentdb_data.documents_2 collection (actual time=2.437..186.944 rows=334 loops=1)
Output: document
Index Cond: (collection.shard_key_value = '2'::bigint)
Filter: ((collection.document OPERATOR(documentdb_api_catalog.@=) '{ "field1" : { "$numberInt" : "42" } }'::documentdb_core.bson) AND (collection.document OPERATOR(documentdb_api_catalog.@=) '{ "array" : { "$numberInt" : "42" } }'::documentdb_core.bson))
Rows Removed by Filter: 99666
Storage Table Read Requests: 98
Storage Table Read Execution Time: 107.827 ms
Storage Table Read Ops: 98
Storage Table Rows Scanned: 100000
Metric rocksdb_block_cache_hit: 4677.000
Metric rocksdb_block_cache_index_hit: 196.000
Metric rocksdb_block_cache_data_hit: 4285.000
Metric rocksdb_number_db_seek: 98.000
Metric rocksdb_number_db_next: 100097.000
Metric rocksdb_number_db_seek_found: 98.000
Metric rocksdb_number_db_next_found: 100096.000
Metric rocksdb_iter_bytes_read: 135359786.000
Metric rocksdb_block_cache_multi_touch_hit: 4677.000
Metric docdb_keys_found: 100097.000
Metric ql_read_latency: sum: 79697.000, count: 98.000
Estimated Seeks: 98
Estimated Nexts And Prevs: 100000
Estimated Table Roundtrips: 0
Estimated Index Roundtrips: 98
Estimated Docdb Result Width: 1285
(25 rows)
All rows are scanned and fetched in 98 requests, since the default fetch size is 1024, and then filtered by the query layer.
The preview allows you to test DocumentDB features on YugabyteDB. Since Yugabyte uses PostgreSQL for its query layer, this is straightforward. However, because the storage differs, indexes need to be specific. Yugabyte has developed a distributed version of GIN and HNSW (pgvector) and still needs to implement indexes for the DocumentDB extension (RUM and Extended RUM). I'll follow https://github.com/yugabyte/yugabyte-db/issues/31634, which tracks this.

Top comments (0)