- DATE:
- AUTHOR:
- PowerSync Product Team
Sync Streams Are Now in Beta
Overview
Sync Streams are in Beta and are now the recommended way to sync data with PowerSync.
The original Sync Rules system was designed to sync data upfront when a client connects — which works well for offline-first apps but creates friction for web apps and other use-cases where you want to sync only the data needed for the current view. Sync Streams address this directly: you define streams of data once (on the server, as with Sync Rules), and your app subscribes to the streams it needs, when it needs them. Multiple tabs, each with their own subscriptions and their own parameters, work independently with no extra state management. Built-in TTL keeps data cached after unsubscribing, so returning to a view doesn't require a loading state.
This Beta release also ships several new query capabilities that were missing in Early Alpha — JOINs, CTEs, multiple queries per stream, nested subqueries, and table-valued functions — making it practical to express complex data access patterns cleanly.
Beta: Sync Streams are in Beta while we collect more feedback. In our terminology, that means they are production-ready and we recommend using Sync Streams for new projects. Sync Rules remain fully supported but are now considered legacy. Sync Rules will be deprecated eventually, and we will communicate a minimally disruptive LTS plan to existing users to help them migrate.
What's new since Early Alpha
JOINs: Express complex relationships with
INNER JOIN/JOINsyntax.
config:
edition: 3 # All new query features require edition: 3 in your sync config
streams:
my_issues:
query: |
SELECT issues.* FROM issues
INNER JOIN projects ON projects.id = issues.project_id
INNER JOIN memberships ON memberships.project_id = projects.id
WHERE memberships.user_id = auth.user_id()Common Table Expressions (CTEs): Define reusable subqueries once and reference them across multiple queries in a stream, avoiding duplication for patterns like "organizations this user belongs to."
streams:
project_data:
with:
my_orgs: |
SELECT * FROM organisations
WHERE id IN (SELECT org_id FROM memberships WHERE user_id = auth.user_id())
queries:
- SELECT * FROM my_orgs
- SELECT * FROM projects WHERE org_id IN (SELECT id FROM my_orgs)
- SELECT * FROM team_members WHERE org_id IN (SELECT id FROM my_orgs)Multiple queries per stream: Combine related queries into a single stream so they share a subscription. Previously, each table required a separate stream.
streams:
user_data:
queries:
- SELECT * FROM settings WHERE user_id = auth.user_id()
- SELECT * FROM notes WHERE user_id = auth.user_id()
- SELECT * FROM preferences WHERE user_id = auth.user_id()Nested subqueries: Query across multiple levels of relationships without denormalizing your schema.
streams:
my_issues:
query: |
SELECT * FROM issues WHERE board_id IN (
SELECT issue_board FROM projects WHERE id IN (
SELECT project_id FROM shared_projects WHERE shared_with = auth.user_id()
)
)Table-valued functions: Expand array parameters from JWT claims or subscription parameters, reaching feature parity with Sync Rules for this pattern.
streams:
project_instances:
query: |
SELECT i.* FROM instances i
INNER JOIN json_each(auth.parameter('project_ids')) AS p
WHERE i.project_id = p.valueThese query features are backed by a new compiler that also ships several internal improvements with direct impact:
Parameter deduplication: When a query references the same value multiple ways (e.g. as both a subscription parameter and inside a subquery), the compiler detects the overlap and merges the lookups.
Query pattern reuse: Identical subquery patterns shared across multiple streams - especially common when using CTEs - now reuse the same internal index rather than creating duplicates, reducing overhead for complex permission models.
Improved validation: Clearer error messages when sync config is invalid, making it easier to identify and fix issues before deploying.
Finally, Sync Stream support is now also available in our TanStack React Query package — useQuery and useQueries accept a streams option — and in the Vue and Nuxt packages via the useSyncStream composable, in addition to the existing React Hooks support. Example usage is documented in the Sync Streams client usage docs.
Getting started
See the Sync Streams overview for quickstart examples, client-side subscription API for all SDKs, and a full reference of stream definition options.
config:
edition: 3
streams:
my_todos:
auto_subscribe: true
query: SELECT * FROM todos WHERE owner_id = auth.user_id()Requirements
PowerSync Service v1.20.0+ (PowerSync Cloud instances already meet this)
Latest SDK versions with the Rust-based sync client (enabled by default in current SDK releases)
config: edition: 3in your sync config
See the minimum SDK version table for details, and instructions for enabling the Rust client on older SDK versions if needed.
Migrating from Sync Rules
Existing Sync Rules configurations continue to work — migration is optional but encouraged. When you're ready:
Generate a Sync Streams draft: The PowerSync Dashboard now includes a Migrate to Sync Streams button that automatically converts your existing Sync Rules into a Sync Streams draft for review before deploying. The output uses
auto_subscribe: trueby default, preserving your existing sync-everything-upfront behavior with no client-side changes required.Review the draft and deploy.
Optionally, migrate individual streams to on-demand subscriptions over time: removing
auto_subscribe: trueand updating client code to use thesyncStream()API where it makes sense for your app.
See the Migration Guide for syntax changes, before/after examples, and client-side update instructions.
Resources
Getting started or evaluating Sync Streams → Sync Streams overview
Writing or debugging a stream query (JOINs, CTEs, subqueries, multiple queries per stream) → Writing queries
Filtering streams by user, JWT claims, or runtime values → Parameters reference
Migrating an existing project from Sync Rules → Migration guide
Looking for a working pattern or demo app → Examples
Feedback and help
Share feedback in our Discord or on GitHub. If you hit issues migrating from Sync Rules or run into query patterns that don't work as expected, please let us know. Feedback from migrations is especially useful at this stage.