Skip to content

feat: Add dbDirectory parameter for custom database storage locations#111

Open
nightfall708 wants to merge 1 commit intopowersync-ja:mainfrom
nightfall708:feat/custom-db-directory
Open

feat: Add dbDirectory parameter for custom database storage locations#111
nightfall708 wants to merge 1 commit intopowersync-ja:mainfrom
nightfall708:feat/custom-db-directory

Conversation

@nightfall708
Copy link

Summary

  • Adds a dbDirectory parameter to PowerSyncDatabase() that allows specifying a custom directory path for the database file
  • Enables storing the database in a shared App Group container, which is essential for iOS apps that need to share data between the main app and extensions (e.g. Share Extensions, widgets)
  • The underlying Kotlin SDK already supports dbDirectory — this change threads it through the Swift API layer

Motivation

Currently, dbFilename only accepts a filename (not a path), and the database is always stored in the hardcoded Application Support directory. This makes it impossible to share the database between the main app and app extensions without going through a cloud round-trip.

Before: Share Extension writes to its own PowerSync database → syncs to cloud → main app syncs from cloud (slow, requires connectivity)

After: Both main app and Share Extension point to the same database file in the App Group container (instant local access)

Usage

let containerURL = FileManager.default.containerURL(
    forSecurityApplicationGroupIdentifier: "group.com.example.app"
)

let db = PowerSyncDatabase(
    schema: schema,
    dbFilename: "powersync.db",
    dbDirectory: containerURL?.path
)

Changes

File Change
PowerSyncDatabase.swift Add dbDirectory: String? = nil parameter to the public API
KotlinPowerSyncDatabaseImpl.swift Thread dbDirectory through to the Kotlin SDK; use it in deleteDatabase()
KotlinPowerSyncDatabaseImplTests.swift Add tests for custom directory creation, file location, and deletion
CHANGELOG.md Document the new feature

Test plan

  • Verify build compiles (swift build ✅)
  • Verify tests compile (swift build --build-tests ✅)
  • testCustomDbDirectory — verifies database is created in custom directory, not the default
  • testCustomDbDirectoryCloseWithDeleteDatabase — verifies all SQLite files (db, wal, shm) are cleaned up from custom directory
  • Existing tests continue to pass (default behavior unchanged when dbDirectory is nil)

…abase storage locations

This enables storing the database in a shared App Group container,
which is essential for iOS apps that need to share data between the
main app and extensions (e.g. Share Extensions, widgets).

The Kotlin SDK already supports a dbDirectory parameter - this change
threads it through the Swift API layer and ensures deleteDatabase()
respects the custom directory.

Usage:
```swift
let containerURL = FileManager.default.containerURL(
    forSecurityApplicationGroupIdentifier: "group.com.example.app"
)

let db = PowerSyncDatabase(
    schema: schema,
    dbFilename: "powersync.db",
    dbDirectory: containerURL?.path
)
```
@simolus3
Copy link
Contributor

Apologies for the slow response on this. We've talked about this internally, and while we generally believe setting a custom directory would make sense, doing this to share a database between processes specifically could be dangerous. There are a number of reasons for that, namely:

  1. No mutex for writes: With WAL mode (enabled in PowerSync by default), readers don't block writers from accessing the database even across different apps. But we can't have concurrent writers, sqlite would return "database is locked" errors for those. The Kotlin/Swift SDKs are not really equipped to handle those (I reasonable strategy would be to retry asynchronously).
  2. We really don't want multiple apps to connect the same database to the PowerSync service at the same time. This would cause all kinds of issues, most likely excessive network consumption and potential integrity violations.
  3. Fixing this would require inter-process coordination, which is non-trivial to do. It's not just about mutexes which we could build with shared memory: If you have two apps open using the same PowerSync database but only one can sync, we still want to share the sync status, Sync Streams and watched queries between the two. We have built this for the web and know it's a lot of work. On native platforms it might be even harder because the two apps might be using different versions of the PowerSync SDK.

So given the concurrency concerns, we don't want to pretend we support app group containers as long as these issues exist. So if we add this API, we at least want a strong warning discouraging shared databases. Do you see potential use-case for changing the directory apart from app group containers? If that's the only or primary motivation, adding that API might be harmful since it suggests databases can trivially be shared across apps when that's not the case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants