From 8a203f93f5e80ee66b4ef88410d61e51c469760e Mon Sep 17 00:00:00 2001 From: Benita Volkmann Date: Mon, 11 May 2026 17:54:27 +0200 Subject: [PATCH 1/6] Consolidate a number of docs updates for upcoming Swift SDK release --- client-sdks/usage-examples.mdx | 9 ++--- sync/streams/client-usage.mdx | 61 +++++++++++++++++++++++++++++++++- sync/streams/overview.mdx | 4 +++ 3 files changed, 69 insertions(+), 5 deletions(-) diff --git a/client-sdks/usage-examples.mdx b/client-sdks/usage-examples.mdx index 7413b46c..39b0fccb 100644 --- a/client-sdks/usage-examples.mdx +++ b/client-sdks/usage-examples.mdx @@ -618,20 +618,21 @@ import JavaScriptCallbackWatch from '/snippets/basic-watch-query-javascript-call ```swift class MyConnector: PowerSyncBackendConnector { override func uploadData(database: PowerSyncDatabaseProtocol) async throws { - let batch = try await database.getCrudBatch() - guard let batch = batch else { return } + guard let batch = try await database.getCrudBatch() else { return } for entry in batch.crud { switch entry.op { case .put: // Send the data to your backend service // Replace `_myApi` with your own API client or service - try await _myApi.put(table: entry.table, data: entry.opData) + // `opDataTyped` preserves SQLite types as a `[String: JsonValue]` dictionary. + // Use `opData` for the legacy `[String: String?]` representation. + try await _myApi.put(table: entry.table, data: entry.opDataTyped ?? [:]) default: // TODO: implement the other operations (patch, delete) break } } - try await batch.complete(writeCheckpoint: nil) + try await batch.complete() } } ``` diff --git a/sync/streams/client-usage.mdx b/sync/streams/client-usage.mdx index 6d0cf50e..19bd0800 100644 --- a/sync/streams/client-usage.mdx +++ b/sync/streams/client-usage.mdx @@ -641,13 +641,72 @@ try await db.connect( ```csharp -await db.Connect(connector, new ConnectOptions { +await db.Connect(connector, new PowerSyncConnectionOptions { Params = new() { ["environment"] = "production" } }); ``` +## Opting Out of Auto-Subscribed Streams + +By default, every stream defined with [`auto_subscribe: true`](/sync/streams/overview#using-auto-subscribe) starts syncing as soon as the client connects. Set `includeDefaultStreams: false` on the connect options to override this for the current connection: the `auto_subscribe: true` flag is ignored, and those streams only sync if the client explicitly calls `db.syncStream(name, params).subscribe()`. The default is `true`, which preserves the existing behavior. + +This is useful when you want a client to decide at runtime which of the default streams to sync — for example, syncing only the workspace the user just selected, or keeping storage minimal on lower-tier devices. To start syncing a previously skipped stream, subscribe to it explicitly; you do not need to reconnect. + +```js +// Connect without syncing auto_subscribe streams +await db.connect(connector, { includeDefaultStreams: false }); + +// Later, opt in to a specific one +const sub = await db.syncStream('workspace_data', { workspace_id: id }).subscribe(); +``` + + + +```js +await db.connect(connector, { + includeDefaultStreams: false +}); +``` + + + +```dart +await db.connect( + connector: connector, + options: const SyncOptions(includeDefaultStreams: false), +); +``` + + + +```kotlin +database.connect( + connector, + options = SyncOptions(includeDefaultStreams = false) +) +``` + + + +```swift +try await db.connect( + connector: connector, + options: ConnectOptions(includeDefaultStreams: false) +) +``` + + + +```csharp +await db.Connect(connector, new PowerSyncConnectionOptions { + IncludeDefaultStreams = false +}); +``` + + + ## API Reference For quick reference, here are the key methods available in each SDK: diff --git a/sync/streams/overview.mdx b/sync/streams/overview.mdx index eb228225..860ede36 100644 --- a/sync/streams/overview.mdx +++ b/sync/streams/overview.mdx @@ -164,6 +164,10 @@ streams: AND order_id IN (SELECT id FROM orders WHERE user_id = auth.user_id()) ``` + +Clients can opt out of auto-subscribed streams at connect time by setting `includeDefaultStreams: false` on the connect options. See [Opting out of auto-subscribed streams](/sync/streams/client-usage#opting-out-of-auto-subscribed-streams) for details. + + ## Client-Side Usage From 883df20ee90304d392486b9250cc9e18c4e59215 Mon Sep 17 00:00:00 2001 From: Benita Volkmann Date: Mon, 11 May 2026 18:51:52 +0200 Subject: [PATCH 2/6] Drop @_spi(PowerSyncExperimental) from migration guide Swift snippet The marker on newClientImplementation was removed in Swift SDK 1.11.0. Pairing this with the broader Swift 1.14 release docs to keep all Swift SDK doc changes on the same branch. --- sync/streams/migration.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sync/streams/migration.mdx b/sync/streams/migration.mdx index 8df67f40..a16077f2 100644 --- a/sync/streams/migration.mdx +++ b/sync/streams/migration.mdx @@ -88,7 +88,7 @@ database.connect(MyConnector(), options = SyncOptions( **Swift:** ```swift -@_spi(PowerSyncExperimental) import PowerSync +import PowerSync try await db.connect(connector: connector, options: ConnectOptions( newClientImplementation: true, From c36dc64c00b17f7f645643ab9ccf9e30d1e9f6ad Mon Sep 17 00:00:00 2001 From: Benita Volkmann Date: Mon, 11 May 2026 19:11:44 +0200 Subject: [PATCH 3/6] Document Kotlin dependency update --- client-sdks/reference/swift.mdx | 15 ++++++++++----- client-sdks/usage-examples.mdx | 4 ++++ 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/client-sdks/reference/swift.mdx b/client-sdks/reference/swift.mdx index 0a573fc4..e5c31aba 100644 --- a/client-sdks/reference/swift.mdx +++ b/client-sdks/reference/swift.mdx @@ -25,10 +25,11 @@ import LocalOnly from '/snippets/local-only-escape.mdx'; -## Kotlin -> Swift SDK - -The PowerSync Swift SDK makes use of the [PowerSync Kotlin SDK](https://github.com/powersync-ja/powersync-kotlin) with the API tool [SKIE](https://skie.touchlab.co/) under the hood to help generate and publish a Swift package. The Swift SDK abstracts the Kotlin SDK behind pure Swift Protocols, enabling us to fully leverage Swift's native features and libraries. Our ultimate goal is to deliver a Swift-centric experience for developers. - + + Earlier versions of the Swift SDK (up to v1.13) shipped a PowerSync Kotlin XCFramework under the hood and abstracted it behind Swift protocols. + + From v1.14 onward, the Kotlin dependency has been removed entirely. The SDK is now implemented natively in Swift, with the PowerSync sync protocol and SQLite extension handled by a small Rust core. + ### SDK Features @@ -295,4 +296,8 @@ See [Supported Platforms -> Swift SDK](/resources/supported-platforms#swift-sdk) ## Upgrading the SDK -Update the version number in `Package.swift` or via Xcode Package Dependencies as documented in the installation instructions: [Installation](/client-sdks/reference/swift#installation) +Update the version number in `Package.swift` or via Xcode Package Dependencies as documented in the installation instructions: [Installation](/client-sdks/reference/swift#installation). + + + **Upgrading to v1.14**: This release removes the internal Kotlin dependency and reimplements the SQLite connection pool natively in Swift. The public API is unchanged, but the pool internals are a full rewrite — we recommend testing queries and CRUD upload flows in your app after upgrading. + diff --git a/client-sdks/usage-examples.mdx b/client-sdks/usage-examples.mdx index 39b0fccb..09c4863b 100644 --- a/client-sdks/usage-examples.mdx +++ b/client-sdks/usage-examples.mdx @@ -636,6 +636,10 @@ import JavaScriptCallbackWatch from '/snippets/basic-watch-query-javascript-call } } ``` + + + As of v1.14, `CrudBatch`, `CrudEntry`, and `CrudTransaction` are concrete `struct`s instead of protocols. Existing code that reads their properties continues to work unchanged, but they can no longer be constructed in user code (for example, in tests or mocks). + From f91c092ae6544f92e1014a410ea017ae69faf48a Mon Sep 17 00:00:00 2001 From: Benita Volkmann Date: Mon, 11 May 2026 19:16:43 +0200 Subject: [PATCH 4/6] Add warning to Supabase guide --- integrations/supabase/guide.mdx | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/integrations/supabase/guide.mdx b/integrations/supabase/guide.mdx index 30872d7f..bfcc35bd 100644 --- a/integrations/supabase/guide.mdx +++ b/integrations/supabase/guide.mdx @@ -18,15 +18,34 @@ allowfullscreen> Used in conjunction with **Supabase**, PowerSync enables developers to build local-first & offline-first apps that are robust in poor network conditions and that have highly responsive frontends while relying on [Supabase](https://supabase.com/) for their backend. This guide provides instructions for how to configure PowerSync for use with your Supabase project. + + Note: We are currently investigating an issue with Supabase logical replication where unused/idle instances have excessive WAL growth, resulting in maxed out disk usage. Supabase seem to have updated the default archive_timeout setting to 2 min, which seems to be part of the issue. The current recommendation for pet/hobby projects is to set a smaller `max_wal_size` and `max_slot_wal_keep_size`: + + ```bash + supabase --experimental \ + --project-ref \ + postgres-config update --config max_wal_size=1GB + ``` + + and also: + + ```bash + supabase --experimental \ + --project-ref \ + postgres-config update --config max_slot_wal_keep_size=1GB + ``` + + Before you proceed, this guide assumes that you have already signed up for free accounts with both Supabase and PowerSync Cloud (our cloud-hosted offering). If you haven't signed up for a **PowerSync** (Cloud) account yet, [click here](https://accounts.powersync.com/portal/powersync-signup?s=docs) (and if you haven't signed up for Supabase yet, [click here](https://supabase.com/dashboard/sign-up)). -For mobile/desktop apps, this guide assumes that you already have **Flutter / React Native / Kotlin / Xcode** set up. + For mobile/desktop apps, this guide assumes that you already have **Flutter / React Native / Kotlin / Xcode** set up. -For web apps, this guide assumes that you have [pnpm](https://pnpm.io/installation#using-npm) installed. + For web apps, this guide assumes that you have [pnpm](https://pnpm.io/installation#using-npm) installed. + This guide takes 10-15 minutes to complete. From 68370d662bcdd1f46baff5afcdcffcd49ef6e841 Mon Sep 17 00:00:00 2001 From: Benita Volkmann Date: Tue, 12 May 2026 12:48:13 +0200 Subject: [PATCH 5/6] tone down includeDefaultStreams option --- sync/streams/client-usage.mdx | 15 ++++++--------- sync/streams/overview.mdx | 4 ---- 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/sync/streams/client-usage.mdx b/sync/streams/client-usage.mdx index 19bd0800..a5110092 100644 --- a/sync/streams/client-usage.mdx +++ b/sync/streams/client-usage.mdx @@ -650,24 +650,21 @@ await db.Connect(connector, new PowerSyncConnectionOptions { ## Opting Out of Auto-Subscribed Streams -By default, every stream defined with [`auto_subscribe: true`](/sync/streams/overview#using-auto-subscribe) starts syncing as soon as the client connects. Set `includeDefaultStreams: false` on the connect options to override this for the current connection: the `auto_subscribe: true` flag is ignored, and those streams only sync if the client explicitly calls `db.syncStream(name, params).subscribe()`. The default is `true`, which preserves the existing behavior. +By default, every stream defined with [`auto_subscribe: true`](/sync/streams/overview#using-auto-subscribe) 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()`. -This is useful when you want a client to decide at runtime which of the default streams to sync — for example, syncing only the workspace the user just selected, or keeping storage minimal on lower-tier devices. To start syncing a previously skipped stream, subscribe to it explicitly; you do not need to reconnect. +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. -```js -// Connect without syncing auto_subscribe streams -await db.connect(connector, { includeDefaultStreams: false }); - -// Later, opt in to a specific one -const sub = await db.syncStream('workspace_data', { workspace_id: id }).subscribe(); -``` ```js +// Connect without syncing auto_subscribe streams await db.connect(connector, { includeDefaultStreams: false }); + +// Later, opt in to a specific stream +const sub = await db.syncStream('my_stream', params).subscribe(); ``` diff --git a/sync/streams/overview.mdx b/sync/streams/overview.mdx index 860ede36..eb228225 100644 --- a/sync/streams/overview.mdx +++ b/sync/streams/overview.mdx @@ -164,10 +164,6 @@ streams: AND order_id IN (SELECT id FROM orders WHERE user_id = auth.user_id()) ``` - -Clients can opt out of auto-subscribed streams at connect time by setting `includeDefaultStreams: false` on the connect options. See [Opting out of auto-subscribed streams](/sync/streams/client-usage#opting-out-of-auto-subscribed-streams) for details. - - ## Client-Side Usage From addfe11f5b814f6327615630d4d64e0121f78190 Mon Sep 17 00:00:00 2001 From: Benita Volkmann Date: Tue, 12 May 2026 14:45:01 +0200 Subject: [PATCH 6/6] Wording polish --- client-sdks/reference/swift.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client-sdks/reference/swift.mdx b/client-sdks/reference/swift.mdx index e5c31aba..99691b0e 100644 --- a/client-sdks/reference/swift.mdx +++ b/client-sdks/reference/swift.mdx @@ -28,7 +28,7 @@ import LocalOnly from '/snippets/local-only-escape.mdx'; Earlier versions of the Swift SDK (up to v1.13) shipped a PowerSync Kotlin XCFramework under the hood and abstracted it behind Swift protocols. - From v1.14 onward, the Kotlin dependency has been removed entirely. The SDK is now implemented natively in Swift, with the PowerSync sync protocol and SQLite extension handled by a small Rust core. + From v1.14 onward, the Kotlin dependency has been removed entirely. The SDK is now implemented natively in Swift, with the PowerSync sync protocol and SQLite extension handled by our [Rust core](https://github.com/powersync-ja/powersync-sqlite-core). ### SDK Features @@ -299,5 +299,5 @@ See [Supported Platforms -> Swift SDK](/resources/supported-platforms#swift-sdk) Update the version number in `Package.swift` or via Xcode Package Dependencies as documented in the installation instructions: [Installation](/client-sdks/reference/swift#installation). - **Upgrading to v1.14**: This release removes the internal Kotlin dependency and reimplements the SQLite connection pool natively in Swift. The public API is unchanged, but the pool internals are a full rewrite — we recommend testing queries and CRUD upload flows in your app after upgrading. + **Upgrading to v1.14**: This release removes the internal Kotlin dependency and re-implements the SQLite connection pool logic natively in Swift. The public API is unchanged, but the internals are a full rewrite. We recommend testing queries in your app after upgrading to this version.