Skip to main content

In Transit Encryption

Data is always encrypted in transit using TLS — both between the client and PowerSync, and between PowerSync and the source database.

At Rest Encryption

The client-side database can be encrypted at rest. This is currently available for:
SQLCipher support is available for Dart/Flutter through the powersync_sqlcipher SDK. See usage details in the package README:

powersync_sqlcipher

SQLCipher support is available for PowerSync’s React Native SDK through the @powersync/op-sqlite package. See usage details in the package README:

npm: @powersync/op-sqlite

The Web SDK uses the ChaCha20 cipher algorithm by default. See usage details in the package README:

npm: @powersync/web

Additionally, a minimal example demonstrating encryption of the web database is available here.
Encryption support is available for PowerSync’s Node.js SDK using better-sqlite3-multiple-ciphers. See usage details and code examples in the Node.js SDK reference.
Encryption support is available for PowerSync’s Kotlin SDK (since version 1.9.0) using SQLite3MultipleCiphers via the com.powersync:sqlite3multipleciphers package. This allows you to encrypt your local SQLite database with various cipher algorithms.Setup:
  1. Replace your dependency on com.powersync:core with com.powersync:common of the same version.
  2. Add a dependency on com.powersync:sqlite3multipleciphers.
  3. Since :core includes a Ktor client implementation, you’ll need to add one manually if you’re not already using Ktor:
    • Android/JVM: io.ktor:ktor-client-okhttp
    • Apple targets (Kotlin/Native): io.ktor:ktor-client-darwin
  4. Use the appropriate encrypted database factory when creating your PowerSyncDatabase:
// Android
val database = PowerSyncDatabase(
    factory = AndroidEncryptedDatabaseFactory(
        context,
        Key.Passphrase("your encryption key")
    ),
    schema = yourSchema,
    dbFilename = "your_database"
)

// JVM
val database = PowerSyncDatabase(
    factory = JavaEncryptedDatabaseFactory(
        Key.Passphrase("your encryption key")
    ),
    schema = yourSchema,
    dbFilename = "your_database"
)

// Kotlin/Native (Apple targets)
val database = PowerSyncDatabase(
    factory = NativeEncryptedDatabaseFactory(
        Key.Passphrase("your encryption key")
    ),
    schema = yourSchema,
    dbFilename = "your_database"
)
Store encryption keys securely rather than hardcoding them in your code.
For more details, see the sqlite3multipleciphers README in the PowerSync Kotlin SDK repository.
Encryption support is available for PowerSync’s Swift SDK (since version 1.10.0) using SQLite3MultipleCiphers. Encryptions keys are configured with the initialStatements parameter on PowerSyncDatabase() which allows running PRAGMA key statements.Setup requirements:The PowerSync Swift SDK depends on CSQLite to build and link SQLite. That package can be configured to optionally link SQLite3 Multiple Ciphers by enabling the Encryption trait. Due to SwiftPM limitations, we can’t directly expose that trait on the Swift SDK.Instead, we recommend directly depending on CSQLite with the encryption trait, which will enable the same for the SDK (since each package can only appear in a build once). Since XCode doesn’t support specifying package traits when adding dependencies, you first need to add a local Swift package as a workaround.
  1. Create a local Package.swift in your project that depends on CSQLite with the Encryption trait:
// swift-tools-version: 6.2
import PackageDescription

let package = Package(
    name: "helper",
    products: [
        .library(name: "helper", targets: ["helper"]),
    ],
    dependencies: [
        .package(url: "https://github.com/powersync-ja/CSQLite.git", exact: "3.51.2", traits: ["Encryption"]),
    ],
    targets: [
        .target(name: "helper", dependencies: [.product(name: "CSQLite", package: "CSQLite")]),
    ]
)
  1. Add a dependency to this local package from Xcode and resolve packages. This enables sqlite3mc for your entire app, including the PowerSync framework.
  2. Configure encryption when opening the database:
let db = PowerSyncDatabase(
    schema: yourSchema,
    initialStatements: ["pragma key = 'your encryption key'"]
)
Store encryption keys securely (e.g., in Keychain) rather than hardcoding them in your code.
For a complete working example, see the SwiftEncryptionDemo in the PowerSync Swift SDK repository.
Support for encryption on other platforms is planned. In the meantime, let us know your needs and use cases on Discord.

End-to-end Encryption

For end-to-end encryption, the encrypted data can be synced using PowerSync. The data can then either be encrypted and decrypted directly in memory by the application, or a separate local-only table can be used to persist the decrypted data — allowing querying the data directly. Raw SQLite Tables can be used for full control over the SQLite schema and managing tables for the decrypted data. We have a React & Supabase example app that demonstrates this approach. See also the accompanying blog post.

See Also