What is OrioleDB?
Short version: OrioleDB is not a new database. It is a different way for Postgres to store table rows. SQL, drivers, and connection strings stay the same. What changes is that an update no longer leaves the old row version sitting in the table for VACUUM to clean up later. Supabase offers it as a public beta you choose when you create a project. It is not ready for production, you cannot add it to a database you already have, and it is the wrong project if what you actually needed was ordinary Postgres at a flat price.
I run Layerbase. We host regular Postgres, not OrioleDB. This post explains the engine from Supabase's October 28 announcement and their OrioleDB docs, then says who should ignore it.
Contents
- The heap, and why updates get expensive
- What OrioleDB changes
- What the benchmark actually says
- The beta limits that matter
- When ordinary Postgres is the right engine
- FAQ
The heap, and why updates get expensive
Postgres stores ordinary table rows in a heap. An update does not overwrite the row. It writes a new version and leaves the old one in place as a dead tuple. A delete does the same. Indexes point at the row's physical location, so the new version usually needs a new entry in every index on the table, including indexes on columns that did not change.
VACUUM reclaims those dead tuples. Autovacuum runs it in the background once a table has accumulated enough of them. On a table that is updated or deleted constantly (order status, inventory counts, a job queue, session rows), autovacuum falls behind. The table and its indexes grow larger than the live data. Queries read more pages than they should. People then tune autovacuum per table, run VACUUM by hand, or rebuild the table with something like pg_repack.
There is a narrower escape hatch already in Postgres. A HOT update (heap-only tuple) can keep the new version on the same page and skip new index entries, but only when no indexed column changed and the page has room. The moment you update an indexed column, every index that points at the physical row is in play again. That is the heap's structural cost, not a setting you forgot.
Heap storage has two other ceilings that show up on big machines. Transaction IDs are 32-bit. After enough transactions, Postgres has to freeze old rows, and if that work falls behind, the database stops accepting writes to protect itself from wraparound. And a primary-key lookup reads the index and then the heap, through a shared buffer pool that every connection contends for.
None of this means a typical application database is in trouble. A table that is mostly inserted and read, and that fits in memory, often never notices. OrioleDB exists for the tables that do.
What OrioleDB changes
OrioleDB plugs in through Postgres's table access method. It is an open-source extension, in development since 2021, and its creators are on the Supabase team. The Supabase beta ships OrioleDB beta19 on Postgres 17.11. You still write normal SQL:
create table orders (
id bigint generated always as identity primary key,
customer_id bigint not null,
status text not null,
updated_at timestamptz not null default now()
);In an OrioleDB project, that table uses OrioleDB. There is no special storage clause to remember. Five differences are the whole design:
- Undo log instead of dead tuples. The previous version of a row goes to an undo log, which is reclaimed on its own. In most cases the table does not fill up with dead tuples, so there is nothing for
VACUUMto clean on that table. - 64-bit transaction IDs on OrioleDB tables. Those tables do not hit 32-bit wraparound. System catalogs, and any table that is still a heap, still use 32-bit IDs. Wraparound is not gone from the cluster. It is gone from the OrioleDB tables.
- Index-organized tables. The row lives in the primary key index. A lookup by primary key reads one structure. Secondary indexes point at the primary key, so an update writes only the indexes whose columns changed. A table with no primary key gets a hidden one.
- A different buffer path. In-memory pages link directly to storage pages, so OrioleDB does not take the shared buffer-mapping lock the heap uses. Page reads are lock-free.
- Copy-on-write checkpoints and row-level WAL. OrioleDB uses copy-on-write checkpoints and row-level WAL to reduce write overhead. Standard Postgres checkpoints flush dirty pages, not the entire buffer pool.
SELECT, INSERT, UPDATE, DELETE, and INSERT ... ON CONFLICT work. EXPLAIN can show an OrioleDB scan (Custom Scan (o_scan) on a primary-key lookup). Connection strings, Row Level Security, and client libraries stay the same, because this is still Postgres.
What the benchmark actually says
Supabase published numbers on DBArena, which it sponsors. The workload is derived from TPC-C. They say it is not comparable to published TPC-C results. The first round compares Supabase Postgres, Supabase with OrioleDB, Amazon RDS, and Google Cloud SQL, from a Small size (2 vCPU, 2 GiB) to 8XLarge (32 vCPU, 128 GiB), in two setups: data that fits in memory, and data about four times larger than memory.
Their headline, from the October 28 post: when the data does not fit in memory, OrioleDB had the highest throughput per dollar of the products they tested, at every size they published. On 8XLarge it did about 1.8x the transactions per minute of Supabase's own heap Postgres, 113,850 transactions per minute. At Small, same price, about 46% more throughput per dollar than heap. When the data fits in memory, the gap shrinks: about 13% ahead of heap at Large, about 29% at 8XLarge, and at Small the heap was faster.
Read that as their measurement of a beta, on their hardware, against their defaults. It is a reason to benchmark a hot, update-heavy table that is larger than RAM. It is not a reason to rebuild a side project whose working set already fits in memory. They say the same thing: read-mostly data in memory sees a smaller difference, and non-B-tree indexes such as pgvector HNSW go through an experimental bridge and may not benefit yet.
The beta limits that matter
From the October 28 post and the docs:
- Not for production. No SLA during the public beta.
- You choose it when you create the project. You cannot add it to an existing project, and you cannot remove it later.
- No point-in-time recovery. Restoring a backup into a new project is unavailable too. Scheduled backups, compute and disk resizing, read replicas, and Postgres upgrades do work.
- Billed the same as standard Supabase Postgres. The storage engine is not a cheaper plan. It is the same meter with a different table format.
CLUSTER,VACUUM FULL, and some other commands do not work on OrioleDB tables. Native B-tree indexes are the ones that perform. Other index types are experimental.- The image does not include
plv8,plls,plcoffee, ortimescaledb-apache. SERIALIZABLEtransactions take a lock on each OrioleDB table they touch, unless you changeorioledb.serializable.- A project is OrioleDB or Multigres, not both.
- OrioleDB is not in the self-hosted Supabase stack yet. Local development is
supabase init --use-orioledbon Supabase CLI v2.119.0 or later.
Supabase sizes OrioleDB's own buffer pools from the compute size and turns shared_buffers down, because OrioleDB tables do not use the heap buffer pool. Those pool settings are not yours to edit. Compression defaults are off. Turning orioledb.default_compress on affects tables created after the change, not tables that already exist.
If you already have a Supabase project, "try OrioleDB" means a new project and a migration into it, then no supported path back. That is a large commitment for a beta with no point-in-time recovery.
When ordinary Postgres is the right engine
Use OrioleDB's beta when all of these are true: a table is updated or deleted constantly, it is large relative to RAM, primary-key lookups dominate, you can start a new project, and you accept no SLA and no point-in-time recovery while you test. Order status, inventory, and queue tables on a large instance are the examples Supabase gives. Believe the benchmark only after you run your own queries.
Skip it when the database mostly serves reads, fits in memory, or is a new application that has not earned a storage-engine migration. Skipping it is not settling. Heap Postgres is the production engine, with VACUUM, HOT updates, and point-in-time recovery available from hosts that offer them. A bloated table on a small database is usually a vacuum and indexing problem, and pg_stat_user_tables will show you dead tuples and the last vacuum before a new engine will.
Layerbase is that ordinary Postgres. It does not run OrioleDB, and it is not going to grow a private storage engine to match a benchmark we did not participate in. Solo is $5/month and Pro is $15/month. Solo keeps one small primary awake. Shared hosting is US East. Pro and up can do point-in-time restore on always-on Postgres, to a new database. There is no high-availability failover and no anon-key Data API. The always-on comparison is the honest list of what the $5 plan leaves out, including region and availability.
If your app already uses a Postgres connection string, the storage engine under the table is not what you are shopping for. Create a Postgres database and point DATABASE_URL at it. If the database is on Supabase, the migration copies the schema and rows onto regular Postgres. Storage, Realtime, edge functions, and GoTrue's hosted login do not come along. Migrating from Supabase to Layerbase lists that split. The October 30 Data API grant change is a separate decision, covered in permission denied for table.
FAQ
Is OrioleDB a fork of Postgres?
No. It is a table access method. Queries are still SQL. The rows of an OrioleDB table are stored in the primary key index, with old versions in an undo log, instead of in the heap.
Can I turn it on for one table in my current Supabase project?
No. Supabase requires you to pick OrioleDB at project creation, and you cannot switch the project back. A single existing project stays on the heap.
Does it remove VACUUM entirely?
On OrioleDB tables, most updates no longer leave dead tuples in the table, which is the work VACUUM exists to undo. System catalogs still use the heap. Do not plan on VACUUM FULL. That command is unsupported on OrioleDB tables.
Will my pgvector index get the 1.8x number?
Do not assume that. Supabase says non-B-tree indexes, including pgvector HNSW, run through an experimental bridge and may not see the gains. The 1.8x figure is their TPC-C-derived result on an 8XLarge instance when the data did not fit in memory.
Does Layerbase offer OrioleDB?
No. Layerbase hosts standard Postgres. If you need the undo-log engine, Supabase's beta is where it currently runs, with the limits above. If you need production Postgres, backups you can restore to a point in time, and a price that does not move with compute hours, start on Layerbase.
Keep reading
- permission denied for table: the Supabase change, and the Postgres underneathOn October 30, 2026, new tables in a Supabase public schema stopped showing up on the Data API until you GRANT them. The error is 42501. A direct connection as the table owner is unaffected. That split is the decision.
- Cloudflare Workers with Postgres: setup, costs, and migrationRun a Cloudflare Worker against Postgres with Hyperdrive. A practical setup, the separate hosting and database costs, and what changes when you leave Supabase.
- Supabase is acquiring Turso. Read this if you build on your own.Supabase announced it is buying Turso, the company behind libSQL, alongside another $150M. Nothing breaks today. The part worth your attention is how few companies now own the default database for small projects, and what that does to pricing later.
- Supabase alternatives: what to use when the meter stops making senseSupabase is a good product with a metered bill and a Postgres-only ceiling. Here is the honest shortlist of alternatives, what each one is actually for, and when you should just stay.