Skip to content
Concepts

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.

CapabilityPostgreSQLMySQLMariaDBSQLite
Typed CRUD and relationshipsYesYesYesYes
Transactions and savepointsYesYesYesYes
Optimistic lockingYesYesYesYes
Foreign-key SET DEFAULT actionYesRejectedRejectedYes
Row lockingFull server formsServer formsServer formsNot supported. A lock clause fails validation
Insert returningComplete rowsGenerated ID plus reload when neededGenerated ID plus reload when neededComplete rows
Multiple schemasYesDatabase catalogsDatabase catalogsNot supported. @@schema is rejected
Structural alter migrationsNative operationsNative operationsNative operationsAtomic table rebuild when required
PostgreSQL extensions and RLSYesNoNoNo

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.