Quick Start
Streams that are configured to auto-subscribe will automatically start syncing as soon as you connect to your PowerSync instance in your client-side application. For any other streams, the basic pattern is: subscribe to a stream, wait for data to sync, then unsubscribe when done.- TypeScript/JavaScript
- Dart
- Kotlin
- Swift
- .NET
Tauri SDK: The JavaScript API shown in the TypeScript/JavaScript tabs throughout this page applies to Tauri as well. Import from
@powersync/tauri-plugin (for PowerSyncTauriDatabase) or @powersync/common (for shared types). See the Connection Parameters section below for how Tauri handles connect-time parameters differently.Framework Integrations
Most developers use framework-specific hooks that handle subscription lifecycle automatically.- React Hooks
- TanStack Query
- Vue/Nuxt
- Kotlin Compose
The PowerSync React package provides three hooks relevant to Sync Stream subscriptions. Each serves a distinct role:
Use this when a component needs data from exactly one stream.
Use this when the number of streams is only known at runtime — for example, when it depends on an array from props or state:
useQuery: queries the local SQLite database and returns live-updating results. It also accepts astreamsoption to subscribe to streams alongside the query — use this when the stream is only needed for that specific query.useSyncStream: subscribes to a single named Sync Stream. Use this when the same stream’s data is needed across multiple queries or components; the subscription lives independently of any particularuseQuerycall and is canceled when the component unmounts.useSyncStreams: the same asuseSyncStreambut for a variable number of streams. Accepts an array of stream options; all subscriptions are canceled when the component unmounts or the array changes.
useQuery with streams: Tethering a Subscription to a Query
useQuery accepts an optional streams option that subscribes to one or more streams and ties their lifecycle to that specific query. This is the simplest option when the stream is only ever needed alongside this one query:useSyncStream: Single Stream
Use this when a component needs data from exactly one stream.useSyncStreams: Variable Number of Streams
Use this when the number of streams is only known at runtime — for example, when it depends on an array from props or state:Type-Safe Stream Wrappers
When you generate your client-side schema from the PowerSync Dashboard or CLI, typed stream wrappers are generated alongside the schema for all SDKs. These catch typos in stream names and parameter names at compile time — mistakes that would otherwise cause silent data-missing bugs only detectable by inspecting sync status. For example, without typed wrappers this fails silently — no error, but data won’t sync:The Generated Code
The schema generator produces typed wrappers at the bottom of your generated schema file. Given streams like:Usage
Use the generated wrappers instead of callingdb.syncStream() directly. Each method returns a SyncStream, so you can chain .subscribe(), .subscribe({ ttl, priority }), and all other methods covered on this page.
- JavaScript/TypeScript
- Dart
- Kotlin
- Swift
- .NET
Type-safe wrappers are only generated for streams that do not have
auto_subscribe: true. Auto-subscribe streams start syncing automatically on connect and don’t require explicit client subscriptions, so no wrapper is generated for them.Checking Sync Status
You can check whether a subscription has synced and monitor download progress:- TypeScript/JavaScript
- Dart
- Kotlin
- Swift
- .NET
TTL (Time-To-Live)
TTL controls how long data remains cached after you unsubscribe. This enables “warm cache” behavior — when users navigate back to a screen, data may already be available without waiting for a sync. Default behavior: Data is cached for 24 hours after unsubscribing. For most apps, this default works well.Setting a Custom TTL
- TypeScript/JavaScript
- Dart
- Kotlin
- Swift
- .NET
How TTL Works
- Per-subscription: Each
(stream name, parameters)pair has its own TTL. - First subscription wins: If you subscribe to the same stream with the same parameters multiple times, the TTL from the first subscription is used.
- After unsubscribe: Data continues syncing for the TTL duration, then is removed from the client-side SQLite database.
Priority Override
Streams can have a default priority set in the YAML sync configuration (see Prioritized Sync). When subscribing, you can override this priority for a specific subscription:Connection Parameters
Connection parameters are a more advanced feature for values that apply to all streams in a session. They’re the Sync Streams equivalent of Client Parameters in legacy Sync Rules.For most use cases, subscription parameters (passed when subscribing) are more flexible and recommended. Use connection parameters only when you need a single global value across all streams, like an environment flag.
Tauri SDK: Since
connect() must be called from Rust for Tauri, connection parameters are passed via SyncOptions in your Rust connector. See the Tauri SDK reference for details on setting up the Rust connector.- TypeScript/JavaScript
- Dart
- Kotlin
- Swift
- .NET
Opting Out of Auto-Subscribed Streams
By default, every stream defined withauto_subscribe: true starts syncing as soon as the client connects. For advanced use cases where the client needs more control over what syncs at connect time, you can set includeDefaultStreams: false on the connect options. The auto_subscribe: true flag is then ignored for that connection, and those streams only sync if the client explicitly calls db.syncStream(name, params).subscribe().
Most apps will not need this option. Defining streams without auto_subscribe: true and subscribing on-demand from the client generally achieves a similar result with less indirection. One scenario where it can help is during a migration from auto-subscribed streams to on-demand subscriptions. You keep the auto-subscribed streams in place so older client versions continue to sync correctly, while newer versions that explicitly subscribe to the streams they need set includeDefaultStreams: false to skip those defaults.
- TypeScript/JavaScript
- Dart
- Kotlin
- Swift
- .NET
API Reference
For quick reference, here are the key methods available in each SDK:| Method | Description |
|---|---|
db.syncStream(name, params) | Get a SyncStream instance for a stream with optional parameters |
stream.subscribe(options) | Subscribe to the stream. Returns a SyncStreamSubscription |
subscription.waitForFirstSync() | Wait until the subscription has completed its initial sync |
subscription.unsubscribe() | Unsubscribe from the stream (data remains cached for TTL duration) |
db.currentStatus.forStream(sub) | Get sync status and progress for a subscription |