R2DBC — Reactive Relational Data Access with Spring
Fast recall
Quick revision
Core answer
ReactiveCrudRepository, R2dbcEntityTemplate, DatabaseClient. R2DBC is not JPA: no lazy loading, no first-level cache, no automatic relationships, no rich criteria API. Transactions work via the auto-configured `R2dbcTransactionManager` plus @Transactional or TransactionalOperator. Pick R2DBC when you are reactive-all-the-way and need streaming queries or genuine non-blocking I/O. In 2026, MVC + virtual threads + JDBC is a strong default; R2DBC earns its place for reactive WebFlux services and streaming row pipelines.Understanding of reactive DB access, limitations vs JPA, transaction semantics, and modern alternatives (virtual threads)
Treating R2DBC like JPA; mixing R2DBC with JPA carelessly; not propagating reactive transaction context
Discuss r2dbc-postgresql LISTEN/NOTIFY streaming, connection pool tuning, reactive transaction propagation, Flyway migration coexistence
Interview-ready guide
Interview answer
R2DBC is Reactive Relational Database Connectivity — a non-blocking alternative to JDBC with drivers for Postgres, MySQL, H2, SQL Server, MariaDB, and Oracle. You consume it through Spring Data R2DBC.
Three entry points
ReactiveCrudRepository— declarative repositoriesR2dbcEntityTemplate— fluent programmatic CRUDDatabaseClient— fluent SQL with parameter binding
What it is NOT
- Not JPA / Hibernate — no auto-flush, first-level cache, lazy loading
- Not a full ORM — relationships are explicit; you fetch and assemble
- No automatic
@OneToManyloading - No second-level cache
- Limited batching
What it IS
- Non-blocking, reactive DB access
- Native Reactor / WebFlux integration —
Mono/Flux - True streaming —
Fluxover millions of rows without loading them all - Reactive transactions via
R2dbcTransactionManager - Backpressure-aware at driver level
Transactions
@Transactionalworks; auto-configuredR2dbcTransactionManager- All operations in the chain run in one reactive transaction
- Programmatic alternative —
TransactionalOperatorplus.as(tx::transactional) - Mixing blocking and reactive in a transaction breaks context propagation
Migrations
- Flyway and Liquibase don't have reactive versions
- Keep a JDBC URL just for migrations; runtime queries use R2DBC
Connection pool
r2dbc-poolis essential- Sizing rule of thumb the same as JDBC:
(2 × CPU) + spindle_count - Watch Postgres
max_connections
R2DBC vs JDBC + virtual threads
- Both are non-blocking
- R2DBC: no JPA, manual relationships, JDBC migrations, high learning curve
- JDBC + virtual threads: full JPA, automatic relationships, native migrations, low learning curve
- R2DBC better for streaming and LISTEN/NOTIFY
- JDBC + VT better for complex domains and most CRUD
When R2DBC wins
- Streaming millions of rows with backpressure
- WebFlux fully reactive — DB is the missing piece
- Simple CRUD without complex relationships
- Real-time streaming via Postgres LISTEN/NOTIFY
The 2026 recommendation
- Default — MVC + virtual threads + JPA / JDBC
- R2DBC sweet spot — reactive WebFlux, streaming queries, LISTEN/NOTIFY, explicit backpressure on huge result sets
- Don't pick R2DBC "for performance" without a streaming or reactive-all-the-way motivation
Strategic answer
- R2DBC is reactive DB access, not a JPA replacement
- Architectural decision, not a performance tweak
- Pick for streaming and reactive-all-the-way
- JDBC + virtual threads covers most cases
R2DBC — Reactive Relational Data Access with Spring
Direct Answer
R2DBC (Reactive Relational Database Connectivity) is a non-blocking alternative to JDBC, with drivers for Postgres, MySQL, H2, MSSQL, MariaDB, and Oracle. You consume it through Spring Data R2DBC — ReactiveCrudRepository, R2dbcEntityTemplate, DatabaseClient. R2DBC is not JPA: no lazy loading, no first-level cache, no automatic relationships, no rich criteria API. Transactions work via the auto-configured R2dbcTransactionManager plus @Transactional or TransactionalOperator. Pick R2DBC when you are reactive-all-the-way and need streaming queries or genuine non-blocking I/O. In 2026, MVC + virtual threads + JDBC is a strong default; R2DBC earns its place for reactive WebFlux services and streaming row pipelines.
Common Mistakes & Pitfalls
Treating R2DBC like JPA; mixing R2DBC with JPA carelessly; not propagating reactive transaction context
Check your understanding
Answer these without looking back at the article.
- What can't you do with R2DBC that you can with JPA?
- How do transactions work across reactive chains?
- Compare R2DBC streaming vs JDBC stream queries
- When would you mix R2DBC and JDBC in one service?
Related interview prep categories
1Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.