Documentation Index
Fetch the complete documentation index at: https://docs.powersync.com/llms.txt
Use this file to discover all available pages before exploring further.
Why Migrate?
PowerSync’s original Sync Rules system was optimized for offline-first use cases where you want to “sync everything upfront” when the client connects, so data is available locally if the user goes offline. However, many developers are building apps where users are mostly online, and you don’t want to make users wait to sync a lot of data upfront. This is especially true for web apps: users are mostly online, you often want to sync only the data needed for the current page, and users frequently have multiple browser tabs open — each needing different subsets of data.The Problem with Client Parameters
Client Parameters in Sync Rules partially support on-demand syncing — for example, using aproject_ids array to sync only specific projects. However, manually managing these arrays across different browser tabs becomes painful:
- You need to aggregate IDs across all open tabs
- You need additional logic for different data types (tables)
- If you want to keep data around after a tab closes (caching), you need even more management
How Sync Streams Solve This
Sync Streams address these limitations:- On-demand syncing: Define streams once, then subscribe from your app one or more times with different parameters. No need to manage arrays of IDs — each subscription is independent.
- Multi-tab support: Each subscription manages its own lifecycle. Open the same list in two tabs? Each tab subscribes independently. Close one? The other keeps working.
-
Built-in caching: Each subscription has a configurable
ttlthat keeps data cached after unsubscribing. When users return to a screen, data may already be available — no loading state needed. - Simpler, more powerful syntax: Queries with subqueries, JOINs, and CTEs. No separate parameter queries. The syntax is closer to plain SQL and supports more SQL features than Sync Rules.
- Framework integration: React hooks and Kotlin Compose extensions let your UI components automatically manage subscriptions based on what’s rendered.
Still Need Offline-First?
If you want “sync everything upfront” behavior (like Sync Rules), setauto_subscribe: true on your Sync Streams and clients will subscribe automatically when they connect.
Requirements
- PowerSync Service v1.20.0+ (Cloud instances already meet this)
- Latest SDK versions with Rust-based sync client (enabled by default on latest SDKs)
config: edition: 3in your sync config
- Minimum SDK Versions
- Enable Rust Client (older SDKs)
| SDK | Minimum Version | Rust Client Default |
|---|---|---|
| JS Web | v1.27.0 | v1.32.0 |
| React Native | v1.25.0 | v1.29.0 |
| React hooks | v1.8.0 | — |
| Node.js | v0.11.0 | v0.16.0 |
| Capacitor | v0.0.1 | v0.3.0 |
| Tauri | v0.0.1 | Always (Rust client only) |
| Dart/Flutter | v1.16.0 | v1.17.0 |
| Kotlin | v1.7.0 | v1.9.0 |
| Swift | v1.11.0 | v1.8.0 |
| .NET | v0.0.8-alpha.1 | v0.0.5-alpha.1 |
Migration Tool
You can generate a Sync Streams draft from your existing Sync Rules in two ways:- Dashboard: In the PowerSync Dashboard, use the Migrate to Sync Streams button. It converts your Sync Rules into a Sync Streams draft that you can review before deploying.
-
CLI: Run
powersync migrate sync-rulesto produce a Sync Streams draft from your current sync config.
auto_subscribe: true by default, preserving your existing sync-everything-upfront behavior so no client-side changes are required when you first deploy.
Next steps: Review the draft, then deploy it (via the Dashboard or powersync deploy sync-config). After that, you can optionally migrate individual streams to on-demand subscriptions over time — remove auto_subscribe: true from specific streams and update client code to use the syncStream() API where it makes sense for your app.
Stream Definition Reference
| Option | Default | Description |
|---|---|---|
query | — | SQL-like query defining which data to sync. Use either query or queries, not both. See Writing Queries. |
queries | — | Array of queries defining which data to sync. More efficient than defining separate streams: the client manages one subscription and PowerSync merges the data from all queries (see Multiple Queries per Stream). |
with | — | CTEs available to this stream’s queries. Define the with block inside each stream. |
auto_subscribe | false | When true, clients automatically subscribe on connect. |
priority | — | Sync priority (lower value = higher priority). See Prioritized Sync. |
accept_potentially_dangerous_queries | false | Silences security warnings when queries use client-controlled parameters (i.e. connection parameters and subscription parameters), as opposed to authentication parameters that are signed as part of the JWT. Set to true only if you’ve verified the query is safe. See Using Parameters. |
Migration Examples
Global Data (No Parameters)
In Sync Rules, a “global” bucket syncs the same data to all users. In Sync Streams, you achieve this with queries that have no parameters. Addauto_subscribe: true to maintain the Sync Rules behavior where data syncs automatically on connect.
Sync Rules:
Without
auto_subscribe: true, clients would need to explicitly subscribe to these streams. This gives you flexibility to migrate incrementally or switch to on-demand syncing later.User-Scoped Data
Sync Rules:Data with Subqueries (Replaces Parameter Queries)
Sync Rules:Client Parameters → Subscription Parameters
Sync Rules used global Client Parameters:Parameter Syntax Changes
| Sync Rules | Sync Streams |
|---|---|
request.user_id() | auth.user_id() |
request.jwt() ->> 'claim' | auth.parameter('claim') |
request.parameters() ->> 'key' | subscription.parameter('key') (subscription parameter) or connection.parameter('key') (connection parameter) |
bucket.param_name | Use the parameter directly in the query e.g. subscription.parameter('key') |