> ## Documentation Index
> Fetch the complete documentation index at: https://docs.powersync.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Room (Beta)

> Use Android Room with PowerSync's Kotlin SDK.

<Warning>
  Room support is currently in a beta release.
</Warning>

PowerSync supports the Room database library for Kotlin (Multiplatform).

<Card title="Maven: com.powersync:integration-room" icon="https://mintcdn.com/powersync/tPs7iOuh1Kx4X1r7/logo/maven.svg?fit=max&auto=format&n=tPs7iOuh1Kx4X1r7&q=85&s=cfad4e6e8aea487603e81a03919ed2dd" href="https://central.sonatype.com/artifact/com.powersync/integration-room" horizontal width="128" height="128" data-path="logo/maven.svg" />

## Features

When adopting the Room integration for PowerSync:

* PowerSync will use the connection pool of the Room database for efficient queries (avoiding e.g. "database is locked" errors).
* Local writes from Room will update watched PowerSync queries, and they will trigger a CRUD upload.
* Writes from PowerSync (including those made by the sync client) will immediately update your Room flows.

## Installation

PowerSync acts as an addon to your existing Room database, which means that (unlike with most other PowerSync SDKs)
you are still responsible for schema management.
Room requires [raw tables](/client-sdks/advanced/raw-tables), as the views managed by PowerSync are incompatible with
the schema verification when Room opens the database.

To add PowerSync to your Room database,

1. Add a dependency on `com.powersync:core` and `com.powersync:integration-room`.
2. Add a dependency on `androidx.sqlite:sqlite-bundled`: Since PowerSync uses the [PowerSync SQLite core extension](https://github.com/powersync-ja/powersync-sqlite-core) (external SQLite extensions are unsupported on
   the platform SQLite libraries on both Android and iOS), you need to bundle a SQLite with your app.
   On the `RoomDatabase.Builder`, call `setDriver()` with a PowerSync-enabled driver:
   ```Kotlin theme={null}
   val driver = BundledSQLiteDriver().also {
       it.loadPowerSyncExtension() // Extension method by PowerSync
   }

   Room.databaseBuilder(...).setDriver(driver).build()
   ```

## Encrypted Databases

When using PowerSync with Room, PowerSync wraps the Room database instead of opening its own connection. To use an encrypted database with Room, implement `SQLiteDriver` by delegating to `PersistentConnectionFactory` and pass that to `RoomDatabase.Builder.setDriver`:

```kotlin theme={null}
class PowerSyncConnectionFactoryAsSqliteDriver(
    private val powersyncFactory: PersistentConnectionFactory
) : SQLiteDriver {
    override fun open(fileName: String): SQLiteConnection {
        if (fileName == ":memory:") {
            return powersyncFactory.openInMemoryConnection()
        }

        return powersyncFactory.openConnection(fileName, null, false)
    }
}
```

Depending on your target platform, pass an `AndroidEncryptedDatabaseFactory`, `JavaEncryptedDatabaseFactory`, or `NativeEncryptedDatabaseFactory` to the wrapper. The factory automatically installs the PowerSync SQLite extension, so you can skip the `loadPowerSyncExtension()` step.

```kotlin theme={null}
val driver = PowerSyncConnectionFactoryAsSqliteDriver(
    AndroidEncryptedDatabaseFactory(context, Key.Passphrase("your encryption key"))
)

val roomDb = Room.databaseBuilder<MyDatabase>(context, "your_database")
    .setDriver(driver)
    .build()
```

## Setup

Because PowerSync syncs into tables that you've created with Room, it needs to know which SQL statements to run for
inserts, updates and deletes.

Let's say you had a table like the following:

```Kotlin theme={null}
@Entity(tableName = "todos")
data class TodoItem(
    // Note that PowerSync uses textual ids (usually randomly-generated UUIDs)
    @PrimaryKey val id: String
    val description: String
    @ColumnInfo(name="created_by") val authorId: String
)
```

To inform PowerSync about that table, include it as a `RawTable` in the schema:

```Kotlin theme={null}
val schema = Schema(
    // For more information on raw tables, see https://docs.powersync.com/client-sdks/advanced/raw-tables
    RawTable(
        name = "todos",
        schema = RawTableSchema(),
    ),
)
```

After these steps, you can open your Room database like you normally would. Then, you can use the
following method to obtain a `PowerSyncDatabase` instance which is backed by Room:

```Kotlin theme={null}
val schema = Schema(...)
val pool = RoomConnectionPool(yourRoomDatabase, schema)
val powersync = PowerSyncDatabase.opened(
    pool = pool,
    scope = this,
    schema = schema,
    identifier = "databaseName", // Prefer to use the same path/name as your Room database
    logger = Logger,
)
```

The returned `PowerSyncDatabase` behaves just like a regular PowerSync database, meaning that you can call
`connect` to establish a sync connection:

```Kotlin theme={null}
powersync.connect(YourBackendConnector())
```

## Usage

To run queries, you can keep defining Room DAOs in the usual way:

```Kotlin theme={null}
@Dao
interface TodoItemsDao {
    @Insert
    suspend fun create(item: TodoItem)

    @Query("SELECT * FROM todo_item")
    fun watchAll(): Flow<List<TodoItem>>
}

// ...

todoItemsDao.create(TodoItem(
    id = Uuid.random()toHexDashString(),
    title = "My first todo item",
    authorId = currentUserId
))

todoItemsDao.watchAll().collect { items ->
    println("This flow emits events for writes from Room and synced data from PowerSync")
}
```

## Local Writes

To transfer local writes from Room to PowerSync:

1. Create triggers on your Room tables to insert rows into `ps_crud`. See [raw tables](/client-sdks/advanced/raw-tables#capture-local-writes-with-triggers) for details.
2. Ensure the `RoomConnectionPool` is constructed with your `schema` (as shown above). When the schema is provided, the pool will notify PowerSync about writes to every raw table referenced in the schema.
3. Alternatively, after performing writes through Room, invoke:

```Kotlin theme={null}
pool.transferPendingRoomUpdatesToPowerSync()
```

This explicitly transfers any pending Room updates to PowerSync if you prefer to control the timing.
