betavoidbase is in public beta. It runs, the API is PocketBase's and is not moving, and the version is still 0.x for everything around that.Help us get it to 1.0
The roadmap

Roadmap

Four sections. The gaps other backends showed us, the shape we want the core to have, the plugins we intend to ship on top of it, and the ecosystem we would rather other people build than build ourselves.

Everything here is a plan, not a shipped feature. An item earns its place by having a design, not by being desirable. In the first section that rule is visible on the comparison pages: a row is amber only when it is listed below, and a gap with no answer yet stays a red cross.

From the comparisons

Writing the comparison pages was the most useful research we have done, because it produced a list of things other people do better. Each item in this section is a row on one of those pages marked amber rather than red.

Transactions and the database limits

Real transactions, and fewer platform limits

PocketBase has interactive transactions and no bound-parameter or column ceiling. Convex is transactional by design. We have neither.

Today
Every write validates first and then runs as one atomic D1 batch. That is atomic, but it is not a transaction: hook code cannot open one, reads inside a batch cannot depend on a write earlier in the same batch, and D1 caps a statement at 100 bound parameters and a table at 100 columns.
The plan
Move an instance's data into its own SQLite-backed Durable Object instead of a D1 database. The object is a single writer, so transactionSync gives real interactive transactions, the caches never need invalidating, and the D1 statement limits stop applying. The database layer already goes through one interface with a swappable implementation, which is what makes this a replacement rather than a rewrite.
Size
Large. The interface exists; the work is the adapter, the migration path for instances that already hold data, and proving equivalence against the existing suites.

Offline

Writes that survive a tunnel

Firebase caches writes on the device and reconciles them when the network returns, and has done for a decade.

Today
Nothing. A request that fails is a request your code has to handle.
The plan
Two pieces, in order. A service worker that queues mutations and replays them on reconnect, which needs no change to the API and works with the existing SDK. Then a client of our own that reads through a local store so a screen renders before the network answers, which is the part that needs the typed client below to exist first.
Size
Medium for the queue, large for the local store. The queue is worth shipping alone, and the plugin that wraps it into an installable app is further down this page.

Types

A typed client generated from your collections

Convex types the whole path from schema to component, so a rename breaks the build. Ours breaks at the call instead.

Today
The PocketBase SDK is typed, but it knows nothing about your collections: a record is a bag of fields, and a renamed field is a runtime surprise.
The plan
Generate a typed client from the collections the instance actually has, the way the schema already generates the API. A command writes it, the build refreshes it, and a rename becomes a compile error. The collection definitions are already data on the server, so nothing new has to be described.
Size
Medium, and it does not touch the server.

Operations

Cloudflare's observability, on by default

Every hosted competitor shows you what your backend is doing. Ours makes you go and look.

Today
Errors reach Workers Logs if your code logs them, and the platform's own request data is there for anyone who opens the dashboard. Neither is set up for you or surfaced anywhere.
The plan
Turn on Workers Observability at deploy so logs and traces are retained without being asked for, sample the request path into an Analytics Engine dataset the deploy already knows how to create, and put the instance's own numbers behind the admin panel: requests, errors, slow endpoints, and which hooks are costing the CPU.
Size
Small for the wiring, medium for the panel screens.

Where we are taking it

Changes to the core that nobody pointed at. They are the shape we want voidbase to have, and the last of them is what both sections after it stand on.

Auth

Better Auth, natively

Void ships Better Auth. voidbase ships PocketBase's. An app built on the voidbase stack has to pick one and work around the other.

Today
Authentication is PocketBase's: auth collections, its token format, its OAuth flow and the SDK's authStore. That is the right default, because wire compatibility is the point of the project and every existing client expects it.
The plan
Better Auth as a first-class option beside it, over the same user records rather than a second set of them. The stack's pages and the instance's API then agree on who is signed in, one session covers both, and Better Auth's own plugins for organisations, passkeys and two-factor become available without us writing each one again. PocketBase's auth stays exactly where it is, because the compatibility depends on it.
Size
Large. The hard part is one identity behind two token formats, not two auth systems living side by side.

Upgrading a running instance

Moving an instance onto a newer release, in place

Every way of running voidbase can be updated except the one that was meant to be the easiest. A CLI install runs one command; a cloud instance waits for us.

Today
voidbase update covers the executable, a global install and a project's dependency, and a deploy puts the new version live. voidbase cloud provisions from the release it holds, so instances that already exist stay on the release they were created with.
The plan
An upgrade for an instance the control plane owns: re-deploy it onto the active release, run the migrations the new version brings, and keep its database, its files, its custom domains and its secrets exactly where they are. Roll it per instance rather than to everyone at once, and make it reversible, because an upgrade you cannot undo is one nobody presses.
Size
Medium. Provisioning already writes a Worker from a release; the work is doing it to an instance that has data, and proving the rollback.

The stack

The stack, finished

It is the newest of the ways to run voidbase and the least complete. It deploys, and that is most of what it does.

Today
Pages, typed routes, your own Drizzle tables and a voidbase instance build into one Worker and go live in one deploy. Everything past that you wire yourself: two notions of who is signed in, collections the frontend knows nothing about, and an admin panel that lives at its own address rather than inside your app.
The plan
Make the two halves know about each other. One session across the pages and the API, which is the Better Auth item above. Collection types generated into the app so a renamed field breaks the build the way a renamed Drizzle column already does. The admin panel mountable under your own route behind your own authorisation. And one command that runs the pages, the backend and a seeded instance together, because two terminals is a thing you tolerate rather than a thing you like.
Size
Medium each, and they are independent. The typed collections are the one that changes how the stack feels.

voidbase cloud

A dashboard for the life of an instance, not its first minute

It provisions an instance beautifully and then has nothing else to say. Everything past the moment it exists happens somewhere else.

Today
Sign in with Cloudflare, name an instance, and it is created in your own account with its database, storage and domain. You can delete it. That is the whole of the surface.
The plan
The things you actually do to a backend after making one: requests and errors over time, logs you can search, backups and a restore that has been tested, custom domains, secrets, superusers, and the upgrade above. Templates, so a new instance can start as something rather than nothing. Teams, so an instance is not tied to whoever happened to click first. Everything the dashboard can do gets a CLI command as well, because a dashboard-only feature is one you cannot script or review.
Size
Large in total, small in pieces. Most of it is surfacing things the instance already knows.

Plugins

pb_plugins, with a marketplace

Every instance ends up needing the same handful of things, and everyone writes them again.

Today
A hook file, copied between projects by hand. There is no way to install one, version it, or find one somebody else wrote.
The plan
A pb_plugins directory beside the hooks, holding installed plugins the same way pb_hooks holds your own code. A plugin declares what it needs, adds routes, hooks, collections and panel screens, and is installed and updated by name. Core plugins ship with voidbase, official ones are ours and versioned with it, and a marketplace lists what the community has published so installing one does not mean trusting a gist.
Size
Large, and the order matters. The loader and the manifest first, because everything else is a plugin once those exist.

The official plugins

Everything below is a plugin, which is why the loader comes first. These are ours: they ship with voidbase, are versioned with it, and are supported like the rest of it. The order is roughly the order we would build them in.

Backups worth relying on

Enterprise backup, as an official plugin

The built-in backup is a zip in the same account as the thing it is backing up.

Today
Backups are archives written to R2 on a schedule, restorable from the panel. Good enough to undo a mistake, not good enough to survive losing the account.
The plan
An official plugin that takes the whole instance, not only the rows. Two modes, because they answer different fears. A complete instance backup captures the database, the files, the configuration and the schema so the instance can be rebuilt from nothing. A data-only backup captures the rows and files for moving between environments or restoring after a bad migration. Both use Cloudflare's own storage and both are scheduled, verified and restorable without a support ticket.
Size
Medium. The archive format exists; the work is completeness, verification, and a restore path that is tested rather than assumed.

Previews

Preview environments, as an official plugin

A pull request that changes the schema cannot be reviewed against production, and reviewing it against nothing is not reviewing it.

Today
A branch build checks the configuration it would deploy with and stops there, which is safe and unhelpful. There is nowhere to click.
The plan
A preview per pull request, in the shape that fits the change. Either a new instance for the branch, using Cloudflare's own preview deployments, seeded from the production schema so the reviewer gets a working address that disappears on merge. Or, where an instance is expensive or the data matters, the same instance with the branch's writes flagged as preview and filtered out of production reads, which makes a preview a query rather than a deploy. The plugin picks based on what the change touches, and the pull request gets the address either way.
Size
Large, and it lands after the plugin loader, because it is the one that exercises every part of it.

AI

Workers AI and Think, as official plugins

The instance already runs on the network that serves the models, and it already runs a Durable Object for realtime. Calling a third-party API to add a chat box is the long way round.

Today
Nothing. A hook can call Workers AI because a hook can call anything, and that is the whole of the support.
The plan
Plugins built on Cloudflare's Think harness, which is a chat agent over Durable Object SQLite with Workers AI behind it. One puts a chat in the admin panel that can read the instance's own schema, records and logs, so finding where something lives is a question rather than a search. One does the same inside a preview environment, where the thing worth asking about is the change under review. And because a Think agent can be driven as a sub-agent over RPC, the third is a chat your own app mounts, scoped to the collections you let it read.
Size
Medium each, and all three want the plugin loader first.

Payments

Payment providers, as official plugins

Taking money is the first thing most projects add and the last thing anyone wants to write a second time.

Today
Nothing in the box. The webhook endpoint is a hook you write, and the reconciliation is yours to get right.
The plan
One plugin per provider over a shared shape, starting with Stripe, Polar and Lemon Squeezy. Each owns its webhook route, verifies signatures, and writes customers, subscriptions and payments into collections you query like any other. Changing provider becomes changing which plugin is installed, and the shared shape is what makes the next provider cheap to add.
Size
Medium for the first. Small for each one after it.

Editing content

Rich text you edit where it renders

Editing a markdown field in an admin panel means editing it away from the page it appears on.

Today
The panel edits records and your site reads them. Nothing links a block on the page to the field behind it.
The plan
A plugin that binds a block on your own site to the field it came from. A signed-in admin gets contenteditable on that block with a markdown toolbar over it, edits in place, and the save writes the field back through the same rules as any other write. The content stays markdown in a collection, so it is still queryable and still exports, and none of it turns into a document only one editor can open.
Size
Medium. A small client script, a field-level permission check, and a toolbar.

Search engines, and the other crawlers

SEO, as official plugins

Anything that serves pages has to answer crawlers, and every project answers them again from scratch with a handful of routes nobody enjoys writing.

Today
pb_public serves static files and a stack app renders pages, so you can write a robots.txt and a sitemap by hand. Nothing generates either from what is actually in your collections, which is where the truth is and where a hand-written copy goes stale.
The plan
Generated from the routes and records that exist rather than kept in step by hand: robots.txt, a sitemap that changes when records do, JSON-LD from schema.org types mapped onto collections, OpenGraph and Twitter tags, canonical URLs so one page has one address, per-route rules for what may be indexed, and llms.txt for the crawlers that are not search engines. Open Graph images rendered on request and cached the way thumbnails already are, so a share card is a field rather than a design job. Deployment skew and asset versioning are on this list too, because they are the same question asked at deploy time: a browser that loaded one version should keep working against that version, and an asset URL should say which version it came from. Cloudflare's Worker versions and gradual deployments are what that would be built on.
Size
Medium, and it splits cleanly. robots.txt and the sitemap are small and useful on their own; the image rendering and the skew handling are the two that need real design.

Installable, and usable on a bad connection

A progressive web app, and the service worker under it

The offline item in the first section is the engine. This is everything you would otherwise assemble around it by hand, once per project, from a manifest you copied off a blog post.

Today
Nothing. A voidbase app is a website. Making it installable, cacheable and useful on a train is entirely yours.
The plan
A plugin that writes the manifest, the icon set and the service worker from what the app already declares, registers it with the parts everyone gets wrong handled: the update prompt, the skip-waiting path, and a way to unregister, because a stuck service worker is the worst bug in this area and the hardest to talk a user through. It precaches the shell and reuses the mutation queue from the offline item rather than inventing a second one, so a write made with no signal replays through the same path whichever page queued it.
Size
Medium, and it lands after the offline queue. Without that queue it is a caching layer with a better name.

Languages

Translations, as an official plugin

Every application that reaches a second country rebuilds this, and what gets rebuilt is usually a JSON file per language and a helper that cannot tell you which keys are missing.

Today
Nothing. A translated field is a field you named yourself, following a convention only your own code knows about.
The plan
Two halves, because they are two problems. Interface strings live in the project, are typed, and fail the build when a key is missing rather than rendering the key to a user. Content translations live in the collections: a field is declared translatable once and the API answers in the language the request asks for, falling back the way you said rather than the way we guessed. Then the parts around both, which is a locale in the route, hreflang and canonical tags handled by the SEO plugin above, and a panel screen showing what is untranslated so you find out before a reader does.
Size
Large. The content half reaches into the query path, which is the part of the server we change most carefully.

Commerce

A shop the other plugins plug into

Once payments, files, auth and editable content are all in the box, what is left of a shop is the part nobody enjoys building.

Today
Nothing. You build it on collections, and everybody builds it differently.
The plan
An official commerce plugin holding the parts that are the same everywhere: products and variants, inventory, carts, orders, tax, shipping, refunds and an audit trail. It declares its extension points, so a payment plugin supplies checkout, a shipping plugin supplies rates, and a plugin of your own supplies whatever your business does that nobody else's does.
Size
Large, and last, because it is the one that assumes all the others exist.

The ecosystem

The plugin loader above is half a system. The other half is somewhere to get things from, somewhere to put things you made, and a reason for anyone to bother. This is the part we most want other people involved in, so it is written down in more detail than our own confidence deserves.

Templates

Templates, and a listing anyone can add to

Starting from nothing is the slowest part of trying anything, and every project that gets past that point started as a copy of somebody's working example.

Today
voidbase init writes empty directories and void init scaffolds a stack app. Neither of them gives you a working example of anything, so the first hour is spent building what somebody else has already built.
The plan
A template is a public repository with a manifest. voidbase init --template <name> starts from one, the cloud dashboard offers them on the create screen, and anyone can publish theirs by adding it to the listing. Official templates are ours and are kept working, and the first of them is this site: voidbase-cloud/voidbase-site is already public, is a real voidbase stack app, and serves the page you are reading, which makes it an honest starting point rather than a demo we wrote to look good.
Size
Small for the mechanism, ongoing for the templates. The listing is the same listing as the marketplace below.

The marketplace

One marketplace for plugins, themes and templates

A gist is not a distribution channel, and an author you have never heard of is not a security model. Every backend that grew an ecosystem grew a supply chain problem at the same time.

Today
Nothing. Installing somebody else's hook means reading their code and pasting it, which is fine once and unworkable at any scale.
The plan
One place, three kinds of thing, and every listing a versioned repository you install by name. Each submission and each update goes through an automated audit that reports what the code reaches for, whether the permissions it asks for match the ones it uses, and what changed since the version you have, in language a person can read before installing. That audit is a first pass and not a guarantee, so its report is published with the listing and you are free to disagree with it.
Size
Large, and the audit is the part that decides whether any of it is worth having.

Paying the people who build it

Creators keeping what they earn, and us not taking a cut of the ecosystem

Free plugin ecosystems get abandoned and paid ones get gouged. The difference is usually who is being paid and for what.

Today
Nothing to sell and nowhere to sell it, which is at least honest.
The plan
Official plugins and themes stay free, as many as we can write, because an ecosystem does not start behind a paywall. Later a subscription may cover a growing basket of specialised official ones, and specialised is the word doing the work there: things most projects will never need, and never something that used to be free. Anyone can charge for what they publish and keep what they earn. We would rather the marketplace itself be paid for by sponsors than by a percentage of everybody in it, which is also the answer on the pricing page.
Size
This is a policy before it is code, and the policy is easier to keep if we write it down now.

Not on this list

Some of the crosses on the comparison pages are staying crosses, and it is more useful to say which than to imply everything is coming.

  • Postgres. voidbase is SQLite-shaped through and through. If your data needs Postgres, Supabase is the answer and always will be.
  • Separate products around the backend. Firebase sells crash reporting, push notifications and analytics as their own services, with their own bills and their own accounts. The plugins above are code that runs inside your instance, in your account, installed when you want them. We are not building the other kind.
  • Server code in other languages. Hooks are JavaScript, because they run in the Worker alongside everything else.
  • Running anywhere. Deployment targets Cloudflare. The standalone binary runs on your own machine, but an air-gapped cluster is not a thing we are building for.
  • Being older than we are. Ecosystem and maturity are earned by time, and no roadmap item fixes them.

Where the first section came from

Each item in it is a row on one of the comparison pages: PocketBase and Convex for transactions and types, Firebase for offline, and all of them for observability. That is the point of writing comparisons honestly: the list of things to build falls out of it.

Found something wrong on this page?

Fix it yourself. The link below opens this file in GitHub's editor and forks the repository for you if you need one, and your change becomes a pull request without leaving the browser.