
Type-safe ORM with expressive SQL DSL, typed predicates, catalog-scoped tables, transactions, joins and aggregations, migrations, reactive query flows, and Ktor-friendly server integration.
Type-safe ORM and SQL DSL for Kotlin Multiplatform.
Kormium gives you an Exposed-like Kotlin API for tables, entities, typed predicates, transactions, migrations, joins and aggregations, while keeping the core portable across JVM and Kotlin/Native. It ships PostgreSQL, MySQL/MariaDB, SQLite, async r2dbc (PostgreSQL and MySQL) and Ktor integration modules.
object App : Catalog
object Users : Table<App, User>("users", ::User) {
val id by Column.UUID().primaryKey()
val name by Column.Text()
val age by Column.Int()
}
class User : Entity() {
var id by Users.id
var name by Users.name
var age by Users.age
}
val db: Database<App> = createDatabase(
host = "localhost",
database = "postgres",
user = "postgres",
password = "password",
)
val adults = db.autocommit {
Users.find {
where { Users.age gtEq 18 }
orderBy DESC Users.age
limit = 50
}
}Users.age gtEq 18), and values are always bound as parameters.Table<App, User> cannot be used inside a Database<Cache>
scope, and the compiler catches that before runtime.transaction { } and
autocommit { }; suspend code uses suspendTransaction { } and
suspendAutocommit { }.kormium-observe turns a query into a Flow that re-emits when the
tables it reads change — for Compose Multiplatform and Android UIs.Kormium is pre-1.0. The public API is usable and tested, but still allowed to change. It is a good fit for experiments, internal tools, prototypes, benchmarks and feedback. Do not make it the only persistence layer for critical production systems yet.
Requires JDK 21+ for JVM builds. The JVM suspend offload path uses virtual threads.
Kormium is published to Maven Central under io.github.kormium.
dependencies {
implementation(platform("io.github.kormium:kormium-bom:<version>"))
implementation("io.github.kormium:kormium-postgres") // PostgreSQL, JVM + Native
// implementation("io.github.kormium:kormium-mysql") // MySQL / MariaDB, JVM + Native
// implementation("io.github.kormium:kormium-sqlite") // SQLite, JVM + Native + Android
// implementation("io.github.kormium:kormium-r2dbc") // async PostgreSQL + MySQL, JVM only
// implementation("io.github.kormium:kormium-observe") // reactive Flow queries
// implementation("io.github.kormium:kormium-migrate") // SQL migration runner
// optional Ktor integration
// implementation("io.github.kormium:kormium-ktor")
// implementation("io.github.kormium:kormium-ktor-di")
// implementation("io.github.kormium:kormium-ktor-koin")
}See Installation for Gradle variants, native system libraries and module details.
| Platform | PostgreSQL | SQLite | Notes |
|---|---|---|---|
| JVM | JDBC/HikariCP; async r2dbc | sqlite-jdbc | The most stable server target |
| Linux Native | libpq | sqlite3 | Covered by CI native tests |
| macOS Native | libpq | sqlite3 | Published artifacts for x64 and arm64 |
| Android | Not shipped | AndroidX SQLite |
kormium-core and kormium-sqlite compile for Android |
| iOS | Not shipped | sqlite3 |
kormium-core, kormium-sqlite and Ktor integration compile for iOS |
| Windows Native | libpq (experimental) | sqlite3 (experimental) | CI runs JVM + native tests on a Windows runner |
| Wasm | Research | Planned | No shipped backend yet |
Kormium does not own schema management — create tables with raw SQL or a migration tool.
db.transaction {
executeUpdate(
"""CREATE TABLE IF NOT EXISTS "users" ("id" uuid NOT NULL, "name" text NOT NULL, "age" integer NOT NULL, PRIMARY KEY ("id"))""",
)
Users.insert(User().apply {
id = Uuid.random()
name = "Ada"
age = 36
})
}
val ada = db.autocommit {
Users.find {
where { Users.name like "A%" }
where { Users.age gtEq 18 }
}
}For deeper examples, start with Quick start and then read Queries.
Runnable samples live under samples/:
| Sample | Shows |
|---|---|
samples:crud-sqlite |
Standalone SQLite CRUD and migrations |
samples:sharding |
Catalog safety and multiple database instances |
samples:sqlite-cache |
SQLite cache in front of PostgreSQL |
samples:cross-instance-cache |
Cross-instance cache invalidation over Redis (rethis) |
samples:ktor-di |
Ktor CRUD with built-in DI |
samples:ktor-koin |
Ktor CRUD with Koin |
samples:r2dbc |
Ktor CRUD on async r2dbc PostgreSQL |
Type-safe ORM and SQL DSL for Kotlin Multiplatform.
Kormium gives you an Exposed-like Kotlin API for tables, entities, typed predicates, transactions, migrations, joins and aggregations, while keeping the core portable across JVM and Kotlin/Native. It ships PostgreSQL, MySQL/MariaDB, SQLite, async r2dbc (PostgreSQL and MySQL) and Ktor integration modules.
object App : Catalog
object Users : Table<App, User>("users", ::User) {
val id by Column.UUID().primaryKey()
val name by Column.Text()
val age by Column.Int()
}
class User : Entity() {
var id by Users.id
var name by Users.name
var age by Users.age
}
val db: Database<App> = createDatabase(
host = "localhost",
database = "postgres",
user = "postgres",
password = "password",
)
val adults = db.autocommit {
Users.find {
where { Users.age gtEq 18 }
orderBy DESC Users.age
limit = 50
}
}Users.age gtEq 18), and values are always bound as parameters.Table<App, User> cannot be used inside a Database<Cache>
scope, and the compiler catches that before runtime.transaction { } and
autocommit { }; suspend code uses suspendTransaction { } and
suspendAutocommit { }.kormium-observe turns a query into a Flow that re-emits when the
tables it reads change — for Compose Multiplatform and Android UIs.Kormium is pre-1.0. The public API is usable and tested, but still allowed to change. It is a good fit for experiments, internal tools, prototypes, benchmarks and feedback. Do not make it the only persistence layer for critical production systems yet.
Requires JDK 21+ for JVM builds. The JVM suspend offload path uses virtual threads.
Kormium is published to Maven Central under io.github.kormium.
dependencies {
implementation(platform("io.github.kormium:kormium-bom:<version>"))
implementation("io.github.kormium:kormium-postgres") // PostgreSQL, JVM + Native
// implementation("io.github.kormium:kormium-mysql") // MySQL / MariaDB, JVM + Native
// implementation("io.github.kormium:kormium-sqlite") // SQLite, JVM + Native + Android
// implementation("io.github.kormium:kormium-r2dbc") // async PostgreSQL + MySQL, JVM only
// implementation("io.github.kormium:kormium-observe") // reactive Flow queries
// implementation("io.github.kormium:kormium-migrate") // SQL migration runner
// optional Ktor integration
// implementation("io.github.kormium:kormium-ktor")
// implementation("io.github.kormium:kormium-ktor-di")
// implementation("io.github.kormium:kormium-ktor-koin")
}See Installation for Gradle variants, native system libraries and module details.
| Platform | PostgreSQL | SQLite | Notes |
|---|---|---|---|
| JVM | JDBC/HikariCP; async r2dbc | sqlite-jdbc | The most stable server target |
| Linux Native | libpq | sqlite3 | Covered by CI native tests |
| macOS Native | libpq | sqlite3 | Published artifacts for x64 and arm64 |
| Android | Not shipped | AndroidX SQLite |
kormium-core and kormium-sqlite compile for Android |
| iOS | Not shipped | sqlite3 |
kormium-core, kormium-sqlite and Ktor integration compile for iOS |
| Windows Native | libpq (experimental) | sqlite3 (experimental) | CI runs JVM + native tests on a Windows runner |
| Wasm | Research | Planned | No shipped backend yet |
Kormium does not own schema management — create tables with raw SQL or a migration tool.
db.transaction {
executeUpdate(
"""CREATE TABLE IF NOT EXISTS "users" ("id" uuid NOT NULL, "name" text NOT NULL, "age" integer NOT NULL, PRIMARY KEY ("id"))""",
)
Users.insert(User().apply {
id = Uuid.random()
name = "Ada"
age = 36
})
}
val ada = db.autocommit {
Users.find {
where { Users.name like "A%" }
where { Users.age gtEq 18 }
}
}For deeper examples, start with Quick start and then read Queries.
Runnable samples live under samples/:
| Sample | Shows |
|---|---|
samples:crud-sqlite |
Standalone SQLite CRUD and migrations |
samples:sharding |
Catalog safety and multiple database instances |
samples:sqlite-cache |
SQLite cache in front of PostgreSQL |
samples:cross-instance-cache |
Cross-instance cache invalidation over Redis (rethis) |
samples:ktor-di |
Ktor CRUD with built-in DI |
samples:ktor-koin |
Ktor CRUD with Koin |
samples:r2dbc |
Ktor CRUD on async r2dbc PostgreSQL |