Exposed R2DBC Library
Latest stable Based on Exposed release 1.11.0
Suspending and
Flow-based persistence helpers for an end-to-end R2DBC path. The caller or framework ownssuspendTransactionand connection context.

Problem
Section titled “Problem”R2DBC changes more than method signatures: driver access, connection ownership, transaction propagation, cancellation, result collection, Spring integration, and testing all need a non-blocking contract. This module provides repository and DSL helpers while leaving the transaction boundary visible.
When to use it
Section titled “When to use it”Choose R2DBC when the driver, framework, transaction manager, and complete request path are non-blocking and the workload benefits from concurrency without dedicating one platform thread per waiting database call. Do not choose it on the assumption that it is automatically faster; latency and throughput depend on the driver, database, pool, query shape, and workload.
Coordinates
Section titled “Coordinates”dependencies { implementation(platform("io.github.bluetape4k:bluetape4k-dependencies:<version>")) implementation("io.github.bluetape4k.exposed:bluetape4k-exposed-r2dbc") runtimeOnly("org.postgresql:r2dbc-postgresql") // select the deployed driver}Core concepts
Section titled “Core concepts”R2dbcRepositoryruns in the currentsuspendTransaction; it does not open one.- Single-value operations suspend; multi-row reads return cold
Flowvalues. - Collect a repository
Flowinside the transaction that owns its connection. - Cancellation can abort collection, but the driver/database determine how promptly server work stops and resources are released.
findPageperforms count and content work separately within the caller’s transaction.
Quick start
Section titled “Quick start”suspendTransaction(db = database) { val actors = repository.findAll(limit = 20).toList() val page = repository.findPage(pageNumber = 0, pageSize = 20)}Keep creation and terminal collection of database-backed flows inside the same transaction boundary.
API by task
Section titled “API by task”| Task | Stable API |
|---|---|
| Single read/write | suspending findById, saveAll, updateById, deleteById |
| Multi-row read | findAll, findBy, findAllByIds returning Flow |
| Page | suspending findPage |
| Audit | auditedUpdateById, auditedUpdateAll |
| Soft delete | suspending writes plus findActive/findDeleted flows |
| Query helpers | CteQuery, QueryExtensions, ReadableExtensions, table helpers |
| Conflict handling | R2DBC batch insert-on-conflict helpers |
Recommended patterns
Section titled “Recommended patterns”Define one coroutine transaction around one business operation. Do not let a repository open an isolated transaction, because several writes then cannot share rollback. Collect database flows before the boundary closes, convert rows to detached values, and keep blocking libraries off the R2DBC call chain.
Integrations
Section titled “Integrations”Spring R2DBC integration can provide transaction context through the framework module. R2DBC cache variants preserve suspending boundaries but introduce their own client lifecycle and failure semantics. Database adapters must explicitly support the selected R2DBC behavior.
Configuration
Section titled “Configuration”Configure the R2DBC ConnectionFactory, pool, driver options, timeouts, and Exposed R2dbcDatabase in the application/framework layer. Size the pool from measured database capacity, not coroutine count.
Failure modes
Section titled “Failure modes”- Collecting a cold database
FlowaftersuspendTransactioncloses loses its transaction/connection context. - Inserting a blocking codec, cache client, or JDBC call into the path blocks coroutine threads.
- Treating cancellation as guaranteed server-side query termination overstates the contract.
- Mixing Spring and manually opened transaction contexts can split one use case across connections.
- Migrating syntax without replacing the driver and tests leaves a half-blocking system.
Operations
Section titled “Operations”Observe pool acquisition, active connections, transaction/query duration, cancellation, timeout, and error signals. Bound result streams, and confirm driver resource cleanup under cancellation and partial consumption.
Testing
Section titled “Testing”Use bluetape4k-exposed-r2dbc-tests with R2DBC drivers and Testcontainers. Test cancellation, rollback, collection within the boundary, pool exhaustion, dialect behavior, and cleanup after failures. A JDBC-only test does not prove the R2DBC path.
Workshops and learning path
Section titled “Workshops and learning path”Read Coroutine transactions, Repository patterns, and Cancellation and testing. The JDBC/R2DBC guide includes migration cost and operational trade-offs.
Limitations
Section titled “Limitations”R2DBC is not an automatic performance upgrade and does not make blocking dependencies non-blocking. The library supplies no driver, universal cancellation guarantee, or implicit transaction.
Release diagrams
Section titled “Release diagrams”These diagrams are loaded directly from README assets published with the 1.11.0 release and pinned to its immutable commit. They describe this manual’s released structure and runtime flows, not later Snapshot changes. Select a preview to open the SVG at the same release commit.
Core R2DBC repository structure diagram
Section titled “Core R2DBC repository structure diagram”Release README: exposed/r2dbc/README.md
R2DBC repository capability map
Section titled “R2DBC repository capability map”Release README: exposed/r2dbc/README.md
R2DBC suspend transaction sequence diagram
Section titled “R2DBC suspend transaction sequence diagram”Release README: exposed/r2dbc/README.md
R2DBC soft-delete visibility flow diagram
Section titled “R2DBC soft-delete visibility flow diagram”Release README: exposed/r2dbc/README.md



