Database portability
You can learn Rent with SQLite and use PostgreSQL in a deployed application without learning a second set of CRUD methods. The generated client shares the same query and mutation API across supported databases.
Some database capabilities differ. Choose them deliberately using the table below. Rent handles SQL syntax, parameter limits, IDs, catalog inspection, migrations, and transaction options for the database you select. You do not need a separate repository implementation for each vendor.
| Capability | PostgreSQL | MySQL | MariaDB | SQLite |
|---|---|---|---|---|
| Typed CRUD and relationships | Yes | Yes | Yes | Yes |
| Transactions and savepoints | Yes | Yes | Yes | Yes |
| Optimistic locking | Yes | Yes | Yes | Yes |
Foreign-key SET DEFAULT action | Yes | Rejected | Rejected | Yes |
| Row locking | Full server forms | Server forms | Server forms | Not supported. A lock clause fails validation |
| Insert returning | Complete rows | Generated ID plus reload when needed | Generated ID plus reload when needed | Complete rows |
| Multiple schemas | Yes | Database catalogs | Database catalogs | Not supported. @@schema is rejected |
| Structural alter migrations | Native operations | Native operations | Native operations | Atomic table rebuild when required |
| PostgreSQL extensions and RLS | Yes | No | No | No |
Portable by default
Fields, relationships, predicates, typed projections, keyset cursors, eager loads, hooks, policies, encryption, external blobs, bulk writes, and transaction closures have one application-facing API. Rent's backend capability profile rejects an unsupported operation instead of silently changing its meaning.
Database-specific behavior
Statement parameter budgets
Rent allows up to 65,535 bound parameters per statement on PostgreSQL, MySQL, and MariaDB, and 32,766 on bundled SQLite. An IN filter uses one parameter per value. Compound keys use one per component. Filters, projections, and pagination values share that budget.
Generated bulk inserts and eager-loading key lists are batched automatically. Arbitrary queries are not split:
doing so could change sorting, aggregate values, or a global limit. An oversized statement returns
DriverError::ParameterLimit with the dialect, actual count, and maximum before execution. It does not include
SQL or parameter values. A rejected statement leaves an open transaction usable.
For a large application-supplied membership filter, reduce the input set or express membership as a database subquery. Split independent writes inside a transaction when they must succeed or fail together. Custom database builds or connection-level restrictions can impose smaller limits, which are reported by the database itself.
The lower-level mutation planner also bounds insert and foreign-key attachment statements. Execute every
statement in a transactional plan on the same transaction. Oversized PostgreSQL DO UPDATE plans and
unconditional bidirectional updates require explicit smaller batches: automatic splitting could change how
duplicate targets are handled. A planning error occurs before any statement is executed.
Referential actions
Cascade, Restrict, and SetNull use the database's foreign-key behavior. SetDefault
works on PostgreSQL and SQLite. MySQL and MariaDB do not support it. Rent rejects that
schema when constructing a MySQL/MariaDB migration catalog instead of silently changing
the action. A SetNull column must be nullable, and a SetDefault value must reference
an existing parent when the action executes.
PostgreSQL 15 or newer also supports onDelete: SetNull(fields: [post_id]) and
SetDefault(fields: [post_id]) to affect only named local foreign-key fields.
These subsets are rejected for MySQL, MariaDB, SQLite, and onUpdate.
See relationship storage.
Native capabilities
Use explicit dialect features when the database offers something valuable that is not portable. PostgreSQL extensions, row-level security, domains, operator classes, and preload requirements are first-class catalog or extension concepts. MySQL and MariaDB retain their server identity and catalog differences. SQLite migration plans model table rebuilds so rows, indexes, and foreign keys can be preserved atomically.
Raw SQL remains available for a database feature Rent has not modeled. Keep that code at a narrow boundary and add a live test for every database it claims to support.
Compile only the required driver using the database setup guide. Use
rent migrate preflight to discover unsupported or risky migration work
before deployment.
