(updated)
|
min. read

PowerSync 2025 Roadmap: SQLite, Web, Speed & Versatility

Conrad Hofmeyr

PowerSync began as a sync engine for apps that need to work offline. But more and more developers are using sync engines for always-online web apps. Why? Because they make web apps super-fast [1], and significantly simplify state management [2]. 

PowerSync has some strong qualities, like how it exposes standard SQLite, and its robust offline capabilities. Yet it has areas where it needs to evolve to work better for online web apps.

Today we are announcing our roadmap for 2025 that will level-up PowerSync for the new era of web apps powered by sync engines,  while preserving our offline & mobile DNA. Since browsers have arguably become the dominant platform for delivering modern applications, we’re doubling-down on web-focused enhancements to accelerate the sync engine revolution.

Before we dive in to our roadmap, we want to take a quick look at the foundation that we’re building on:

The principles guiding us: SQLite front and center

In 2024 we made substantial progress with the core PowerSync product and grew our community by 16x [3].

The number one product principle that has guided us is to provide an open-source real database on the client-side, with a specific focus on SQLite [4]. This is as opposed to some kind of cache, key-value store or proprietary relational datastore [5].

This approach leverages the power of SQLite and its ecosystem:

  • SQL functionality & concepts: Millions of developers are already well-versed in SQL constructs and syntax, which means that there’s an instant familiarity with using SQLite. It also means having access to its rich functionality such as aggregations, joins, advanced indexing and JSON support [6].
  • Ecosystem & extensibility: SQLite brings a lot with it: You can use popular ORMs that you’re already familiar with, such as Drizzle, Kysely and Drift. You can use SQLite extensions such as SQLCipher for encryption and FTS5 for full-text search [7]. You can use standard tools for inspecting the database and doing more in-depth debugging. You get all the benefits of the SQLite community and the innovation around it: SQLite just keeps becoming more popular, and people keep doing more new interesting things with it.
  • Performance & maturity: SQLite is also really fast, and extremely battle-tested: the SQLite team estimates that there are more than a trillion SQLite databases deployed, and every line in the codebase has 600 lines of test code.

The ubiquity of SQLite also creates opportunities for adopting PowerSync in the SQLite “installed base”: wherever you find SQLite, you can likely use PowerSync too [8].

How we use SQLite is related to another guiding principle: Low lock-in. PowerSync is designed to be a “pluggable middleware” layer rather than a high lock-in monolithic system. It sits between popular backend databases on the server-side, and SQLite on the client-side. Replacing it with a different sync engine is fairly straightforward [9]. Since PowerSync is built to work with open technologies and is itself open too, you can have an end-to-end stack optimized for low risk.

SQLite marches on to the web

SQLite is best known as a database for mobile apps, desktop apps, and other embedded use cases. But lately it’s also becoming a force to be reckoned with on the web.

We’ve written extensively about the evolution of SQLite persistence in web browsers. The early implementations were hack-y, but we’ve reached a point where using it is much more mature. By letting SQLite use filesystem storage via the OPFS browser APIs, the performance is substantially improved compared to the previous common practice of persisting SQLite block data in IndexedDB, which is essentially a hack!

I was recently speaking to a product VP at a database company about embedded databases, and he told me: “Clearly, SQLite has won”. We are betting that SQLite will win the web too, because it strikes the best balance between powerful capabilities and being lightweight [10].

Roadmap for 2025: Leveling-up on the web

So how should PowerSync evolve to meet the needs of web apps? We started by taking a deep look at how we currently stack up:

  • Sync Rules defined server-side only: PowerSync currently requires defining “Sync Rules” upfront on the server-side to specify what data to sync to which client. From the moment when a client connects to PowerSync, all data that they are supposed to have will sync as quickly as possible. Sync Rules can make use of dynamic parameters from the client-side, but the architecture still limits flexibility. When you’re developing web apps, it’s more intuitive to dynamically request data from the client-side at runtime, since the client is almost always online.
  • Managing client-size storage size: When the client is generally always online, it’s less of a concern if some data is not present in client-side storage, since you can easily sync data from the server at will. This means that you can treat the client-side storage more like a cache and expunge data from it if you want. It’s possible to accomplish this with PowerSync’s client parameters, but we don’t have elegant built-in tooling for this.
  • Web performance: Client-side performance is not fully optimized for web apps yet. For example, PowerSync currently refires “live queries” when any row in the underlying tables has changed. This leads to performance limitations with complex queries used in UIs displaying lots of information, as you would find in sophisticated web apps.

Accordingly, we decided on these key items for our 2025 roadmap:

1. On-demand syncing of data in addition to pre-syncing data

We’ll introduce the ability to sync data on-demand from the client at runtime. This will tie into the concept of “buckets” (logically-grouped subsets of your data): We will have On-Demand Buckets as well as Pre-Synced Buckets — the latter refers to what is currently supported by PowerSync [11].

On-Demand Buckets will eliminate the need to design Sync Rules upfront based on what kind of data you anticipate will be needed by clients. You can simply request specific data at any time in your client-side code [12]

On-Demand Buckets also open up the ability to do “hybrid queries” — i.e. combining data that is already present in the client-side SQLite database with data synced on-demand from the backend database; or in other words, combining “offline” & “online” data.  

We will also provide Caching Helper APIs in the client SDK that make it easier to manage which buckets should be kept on the device vs. which can be expunged [13]. It will include time-based caching: setting an “expiration time” for buckets.

2. Web performance optimizations

We will focus on speeding up initial sync as well as client-side query performance on the web. This is critical since creating super-fast apps with instantly-responsive UI/UX is one of the primary value propositions of sync engines on the web.

This will include things such as compression of the data traveling over the network, “prioritized syncing” (being able to prioritize certain buckets of data to sync before others), and an incrementally-updating version of our live query / watched query APIs, to avoid re-running entire queries continuously whenever any row in an affected table is updated.

2025 roadmap beyond the web

We’re also planning major enhancements focused on all users, not just web: 

  • Improved querying flexibility by syncing from incrementally materialized views: PowerSync currently has limited querying flexibility in Sync Rules, e.g. when it comes to multi-level joins and many-to-many relationships. Therefore, we’ll introduce the server-side ability to create materialized views that you can sync from, which are automatically incrementally updated using an Incremental View Maintenance (IVM) or a similar algorithm.
  • Simplified Sync Rules mental model: Our “mental model” is more complex than necessary for many use cases. To address this, we will introduce Simple Sync Rules that can be used for per-user data and global data with a simplified syntax, while still allowing for Advanced Sync Rules that allow explicitly naming buckets and making use of parameter queries.
  • Developer onboarding experience: It takes too long to get started with PowerSync. Self-hosting our Open Edition for local development is also painful. Accordingly, we will optimize the onboarding journey for PowerSync, focused on two “golden paths”: (1) PowerSync Cloud — We have a range of improvements planned to the PowerSync Dashboard, including integrating serverless cloud functions into the stack for backend functionality. (2) PowerSync Open Edition + CLI: We have a substantial set of improvements planned!

What we’re building towards

Our aim is to provide optionality to optimize for offline and/or online use cases.

This ensures that PowerSync can adapt as you expand the scope of your software project or product: For example, you may start with building an online web app and later realize you want to also offer an offline-capable desktop or mobile app. Or the other way around. Whichever way you go, PowerSync will have you covered.

  • For always-online apps: On-Demand Buckets with the ability to temporarily “cache” them on the client and expunge them later.
  • For offline-capable apps: Pre-Synced Buckets that ensures data will be available on-device before a user unexpectedly goes offline [14].
Click to enlarge

We will also continue to go all-in on open technologies, with a major focus on SQLite.

It starts now

We have already taken the first steps towards our product vision:

  • On January 28th, 2025 we released support for using OPFS as a virtual file system (VFS) for SQLite on the web. Our testing showed significant performance gains.
  • On January 21st, 2025 we introduced the ability to use your own SQLite extensions with OP-SQLite on React Native. This is the first step toward better support for custom extensions in general [7].
  • On January 15th, 2025 Simon Binder joined our team. Simon is prominent in the SQLite community, known for creating and maintaining the Drift library for Flutter. He will help us accelerate many of our 2025 goals.

It’s an exciting time for web apps: sync engines make it easier and faster to build much higher-quality web apps. We believe, along with a growing cohort of developers, that sync engines are the application architecture of the future — and they will define the new baseline for modern web apps. Stay tuned for updates!

Questions? Feedback? 

Please feel free to get in touch or talk to us on Discord.

Footnotes

[1] Sync engines allow your app code to make use of a local client-side database that automatically syncs with a backend database in the background. This means there’s zero network latency involved in working with data. Because of a reduced reliance on the network, it also means better reliability and availability for the user. When users are online, data is typically synced in real-time, allowing for real-time multi-user collaboration. We’ve written about all of this before here.

[2] For developers, sync engines are emerging as the new preferred way of dealing with state: They make state transfer and state management much easier than working with request/response APIs — which involve a ton of drudge work for developers. Sync engines abstract away a huge amount of complexity that normally necessitates that drudge work — almost everything related to APIs and dealing with the unpredictability of moving data over the network (e.g. error handling and rollbacks). And we’re not just talking about discrete state transfer, but also keeping state up-to-date in real-time on the client and reconciling those real-time updates with local state. We envision sync engines disrupting REST, GraphQL and gRPC — and those technologies becoming legacy ways of dealing with state transfer and state management in applications. We previously wrote about this here and here

[3] After launching PowerSync as a standalone sync engine in late 2023, in 2024 we mainly focused on maturing the core product: We added support for MongoDB and MySQL as backend source databases in addition to Postgres. We moved to an open-core model, releasing the Open Edition of PowerSync, which developers can freely use and self-host. We expanded our set of client SDKs to include Kotlin Multiplatform and Swift in addition to Flutter, JavaScript web and React Native. We added support for ORMs including Kysely, Drift and Drizzle. We shipped supporting tools, including monitoring & alerting for managing PowerSync in production. We implemented performance optimizations. The list goes on 😄

[4] Our initial focus is SQLite because we see it as the top choice, but we may make this more pluggable in the future and support other popular open-source databases on the client-side. Something else you might wonder about is — why does PowerSync not support SQLite on the backend too? It currently only supports Postgres, MongoDB and MySQL as backend databases. There is a case to be made for this and it’s something we may support in the future. SQLite-to-SQLite sync could work well for scenarios where you have per-user data, and even for situations where you’re sharing data in a point-to-point way. However, many use cases have a large set of data that’s shared between users. In a situation like this, we believe the most sensible way to solve it is to use a database designed for a high volume of shared data on the backend (e.g. Postgres, MySQL, MongoDB) and SQLite on the client-side containing the data relevant to a specific user. Syncing between these backend databases and SQLite on the client-side introduces a unique set of challenges — which is what PowerSync is focused on. Another way of looking at it is that PowerSync supports the most popular backend databases on the server-side, as well as the most popular embedded database on the client-side. 

[5] How do we think about the key-value stores provided by state management libraries? There’s an argument to be made that every client-side key-value store or cache eventually approaches the complexity of an actual database. Which is why we figured putting a real database like SQLite on the client-side is the way to go. There’s also some downsides to how state management frameworks tend to work: You typically need to define a lot of things centrally, such as what actions are allowed on the state. With a real database on the client-side, components directly read and write on the database, allowing dealing with state to be decentralized to individual components. With SQLite paired with PowerSync, the local database also provides a consistent view of the data, meaning you don’t need to keep track of cache invalidation and keep different instances of the data consistent with each other.

[6] These are some of the major reasons why we originally set out to build a SQL & SQLite focused sync engine: because of SQL’s universality and how effective SQLite is for advanced querying.

[7] It’s possible to use any other SQLite extensions such as Spatialite, sqlite-vec and more — we are working on better surfacing and documenting this

[8] In fact, the core of PowerSync is structured as a SQLite extension, making it very pluggable to existing SQLite “installations”. For existing installations of SQLite, syncing the data in it is becoming more and more of a table stakes feature, for collaboration, multi-device access and backups.

[9] You most likely wouldn’t even need to change your client-side queries or ORM code if you were to do this.

[10] Some developers may still have concerns about using SQLite for persistence on the web — such as its bundle size and performance. Our stance is that these factors are already not a major concern for most web apps, and their impact will further diminish over time, e.g., bundle size will be less and less of a concern because of increasing bandwidth (and compression).

[11] Whereas Pre-Synced Buckets are persistent in the PowerSync Service, On-Demand Buckets will be created on-demand in the PowerSync Service, by doing a snapshot from the source backend database and then keeping track of updates through the CDC stream. Least recently used (LRU) On-Demand Buckets will be garbage-collected in the PowerSync Service. If a client tries to use an On-Demand Bucket that was already garbage-collected, it will be re-created dynamically in the PowerSync Service. We are still determining the details of how authorization/permissions will work — this will likely involve specifying allowed queries in the Sync Rules file.

[12] Note that to go to production, for security purposes you will still need to specify permissions/authorization to ring-fence what data clients are allowed to sync/query. See preceding point.

[13] This will include the ability to automatically combine parameters for data needed across multiple UI components and/or multiple browser tabs.

[14] The benefit is that you don’t have to care about where in the lifecycle of the application to sync/query the data, and it therefore maximizes the probability that data will be available on-device before a user unexpectedly goes offline.

Subscribe to receive PowerSync updates
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

By clicking "Subscribe" I agree to opt-in to PowerSync's mailing list
and accept the Privacy Policy.