Now Reading: The browser is your database: Local-first comes of age

Loading
svg

The browser is your database: Local-first comes of age

NewsFebruary 26, 2026Artifice Prime
svg9

Once upon a time, we had mainframes with simple, nonprogrammable consoles. All the power was centralized. Then, Gates and Jobs put a personal computer on every desk. The power was distributed. Then, the internet came along, and the browser became the most popular application in the world. The power moved back onto the server, the cloud became king. Now, that pendulum is swinging back.

This article is a first look at the local-first movement, and the new technologies embedding feature-rich data storage options directly into web browsers.

PGLite: The database in your browser

The modern browser is a beast, the result of years of intensive development and real-world testing. Today’s browser typically runs on a very capable machine. Yet, like a pauper, it must ask the server every time it wants some data. Browser state is just a temporary shadow, eradicated every time the screen refreshes. The loading spinner, the UI waterfall, the click-and-wait; these are all effects of our ongoing dependency on the back end for persistent state.

But an alternative is emerging. The idea is to embed a relational database directly in the browser, with a slice of the data, and let a synchronization (sync) engine keep everything consistent. The browser interacts with a local datastore that is synced to the server in the background. This means instant interactivity on the front end while maintaining symmetry with the back end. This next-generation browser has a more resilient state-of-record, not just a temporary cache.

Several factors have emerged to make the browser a more robust datastore, including IndexedDB and WebAssembly, paving the way for tools like the in-browser NoSQL datastore, PouchDB. But probably the star of the show these days is the PGLite SQL database.

Of course, everything comes with tradeoffs. There are architectural implications to moving the database into the browser. But the most significant change is the gradual distancing from two of the bedrocks of web development: JSON and REST.

The isomorphic future

I recently wrote about how WinterTC moves us toward the dream of isomorphic JavaScript, where the server and client are exactly the same. The next stage is achieving similar homogeneity across datastores. That has only recently become possible with the maturation of WASM, which runs a fully-featured PostgresSQL instance in the browser. That instance, the WASM database, is PGLite.

Although SQLite can get you close to an enterprise database in the browser, PGLite is literally the same database you would run in the data center. It eliminates the friction of dialect. The WASM runtime (really a wonder of the modern programming world) makes PGLite a lightweight build of the actual Postgres codebase.

All of this means we are nearer than ever to a thick client. Of course, there are nuances to be considered, and there will be twists and turns along the path.

Shape-based syncing

Even if the API and implementation are the same, we can’t just create a shard of the entire database in the browser. It’s too big, and it would be insecure anyway. We only want the data the specific user needs for a given session.

An influential idea is “shape-based” syncing. This was popularized by ElectricSQL, which is also the force behind PGLite. A shape is something like a view. It takes one or more queries and uses them to populate the client-side database with a segment of the relevant data. Only the server holds the full truth. The client subscribes to a specific shape within the server (e.g., SELECT * FROM issues WHERE assigned_to = 'me').

Under the hood, syncing relies on Postgres’s native Logical Replication protocol. The sync engine is a middleware consumer. It listens to the database’s write-ahead log (the real-time stream of all changes happening on the server). When a change occurs that matches a client’s subscribed shape, the engine pushes that specific update down the background WebSocket to the browser’s PGLite instance. This activity is bidirectional. Local writes are applied instantly to the UI, then queued and streamed back upstream to the central database, while the engine handles the necessary conflict-resolution logic.

In the old days of progressive web apps (PWAs), you had to write imperative code to replay failed requests when the user came back online. The technique worked but it was brittle, and not a great developer experience. Modern sync engines offer a more elegant solution by doing the work themselves.

At this point, you might be thinking: “But the browser is ephemeral! Users clear their cache!”

The sync engine address this natural objection. To understand how, think about the architecture of Git:

  • The remote database (GitHub) is the source of truth.
  • The local database (your laptop) contains the working data.

If a user clears their browser cache, they haven’t lost their data. They’ve simply deleted their local repository. When they log in again, the sync engine essentially performs a git clone, pulling their “shape of data” back down to the device.

Conflict-free replicated data types

But what happens if two users edit the exact same data while offline? In a standard database, the last write would overwrite the previous one. The syncing logic needs to be very sophisticated indeed, to handle a multitude of clients operating on shapes and continually dumping their syncs to the central datastore.

This is where CRDTs (conflict-free replicated data types) come in.

CRDTs are an esoteric sounding set of mathematical constructs with practical applications for the syncing problem. These data structures (like a Map or a List) are designed to be merged mathematically. It’s the difference between a Git merge conflict (which stops work and requires human intervention) and Google Docs (which merges everyone’s typing automatically). By using CRDT logic, sync engines ensure users’ offline edits are never lost; instead, they are seamlessly combined when the connection is restored.

Now, let me preempt what you might be thinking next: This is a lot of additional architecture. I mean, now we have two databases, a syncing engine, and that “shape” appears to be a duplication of a SELECT statement that should live on the server.

We have in a sense taken distributed computing, a classic hard problem, and split it at the datastore. We are doing this to avoid the clunkiness of loading data, but at the expense of a known pattern: The JSON API (and REST).

If we are willing to do all this, we must be hoping to gain something of great value from it, right?

Outgrowing the JSON API

This new approach makes something possible that web developers have been chasing for 20 years: the desktop-class experience.

By interacting with local data, a responsiveness is attainable on the UI that is simply out of reach when relying on direct network calls. Pulling in a full-blown PostgreSQL instance is a thoroughgoing solution that avoids half-measures like local caches. On top of that, it produces another interesting potential win in developer experience.

By eliminating the back-end API, we toss out a whole layer of coupling that web developers have traditionally had to deal with. The goal is to somehow avoid manually translating client-side data into a transport format, then back into a datastore format, and then back again. (Frameworks like HTMX are also working toward this ideal, although they approach it differently.)

In the ideal of local-first data, we don’t have to do any of that marshaling of JSON. We just write the SQL statement that we want, and the sync engine automatically handles the transport (based on the rules we’ve defined). We no longer write a GET /todos endpoint. Instead, we write an SQL query in our component: SELECT * FROM todos.

IndexedDB and OPFS

While PGLite is fascinating technology, it isn’t the only story on the local-first data front. It’s actually part of a larger constellation of technologies. After all, developers have always found places to stash data: namely, localStorage, cookies, and IndexedDB.

IndexedDB is a real attempt to give the browser a database (and indeed, it can be used as a quick way to back a PGLite instance) but it’s hamstrung by a notoriously clunky API and performance limitations. It is more like a file system bucket than a database engine. It offers no support for complex queries, joins, or constraints. To do anything interesting, you have to write the database logic yourself in JavaScript, pulling data into memory to filter it, which destroys performance. All of which is to say, it’s messy for real-world use cases.

IndexedDB was a necessary stepping-stone, but it’s not a final destination. The foundation of the modern era was built by WebAssembly and the Origin Private File System (OPFS). These are the technologies that let us stop re-inventing databases in JavaScript and start porting proven engines directly into the client.

The high-speed file system: OPFS

While it sounds like an obscure browser spec, OPFS is important to modern local-first architecture. Where WASM provides the runtime, OPFS provides the file system.

OPFS finally gives the browser direct, high-performance access to the user’s hard drive. Unlike IndexedDB, which forces us to read/write entire files or objects, OPFS allows for random-access writes. This means a database like PGLite can modify a tiny 4KB page of data in the middle of a 1GB file without rewriting the entire thing. This is the missing link that allows server-grade databases to run in the browser with near-native performance.

The NoSQL alternative: RxDB

If PGLite is the champion of the “SQL on the client” movement, RxDB (Reactive Database) is the NoSQL equivalent. It inherits from PouchDB, an in-browser NoSQL database that has been in real-world use for many years.

While PGLite focuses on bringing the structure of the server to the client, RxDB focuses on the behavior of the modern UI. It is designed around reactivity (hence the Rx prefix). In a standard database, you run a query and get a result. In RxDB, you subscribe to a query:

// In RxDB, the database IS the state manager
db.todos.find().$.subscribe(todos => {
  render(todos);
});

When the sync engine pushes new data from the server, your UI updates instantly. You don’t need a state management library like Redux or Pinia because the database itself is the source of reactive truth.

Conclusion

The browser is no longer just a document viewer or simple terminal interface. But the emerging local-first architecture is a radical departure from our familiar REST and REST-like solutions. It brings its own complexities.

With the unification of the runtime (WinterTC) and the arrival of industrial-grade local databases (PGlite and RxDB), the browser could potentially be a full-bore application platform. But will it supplant the known way of doing things? Not all at once, and not quickly. Familiarity is a huge ballast in the programming world.

Local-first + syncing could someday knock the crown off JSON and REST. But first, it will have to prove its viability in the real world.

Original Link:https://www.infoworld.com/article/4133648/the-browser-is-your-database-local-first-comes-of-age.html
Originally Posted: Thu, 26 Feb 2026 09:00:00 +0000

0 People voted this article. 0 Upvotes - 0 Downvotes.

Artifice Prime

Atifice Prime is an AI enthusiast with over 25 years of experience as a Linux Sys Admin. They have an interest in Artificial Intelligence, its use as a tool to further humankind, as well as its impact on society.

svg
svg

What do you think?

It is nice to know your opinion. Leave a comment.

Leave a reply

Loading
svg To Top
  • 1

    The browser is your database: Local-first comes of age

Quick Navigation