Database Overview
Morphis provides a shared model layer with connection management and Drizzle-powered database support.
If you want deeper low-level ORM details, start with the Drizzle ORM overview .
Supported drivers
- D1: Morphis D1 connection flow and Drizzle Cloudflare D1 guide
- SQLite: Morphis SQLite connection flow and Drizzle SQLite guide
- PostgreSQL: Morphis PostgreSQL connection flow and Drizzle PostgreSQL guide
- MySQL: Morphis MySQL connection flow and Drizzle MySQL guide
- MariaDB: Morphis MariaDB connection flow and Drizzle MySQL guide
- Microsoft SQL Server: Morphis MSSQL connection flow and Drizzle MSSQL guide
Core idea
A model declares its table and connection, while the framework handles the underlying query builder and runtime driver selection.
For most application code, use Morphis model methods such as findAll, findOne, findByPk, create, update, destroy, upsert, and count. Morphis now also supports explicit transactions through the model layer, so you can keep CRUD code on Morphis models instead of dropping to raw Drizzle for normal transactional work.
Transactions with models
Use ConnectionManager.getTransaction(connection?) when you want explicit commit and rollback control across any Morphis models that share the same connection.
import { ConnectionManager } from 'morphis'
const transaction = await ConnectionManager.getTransaction()
try {
const created = await Post.create({ content: 'draft' }, transaction)
await AuditLog.create(
{ message: `created post ${created.id}` },
{ transaction },
)
await Post.update(
{ content: 'published' },
{ where: { id: created.id }, transaction },
)
await transaction.commit()
} catch (error) {
await transaction.rollback()
throw error
}If you need a non-default database, pass the connection name:
const transaction = await ConnectionManager.getTransaction('analytics')Morphis accepts the transaction in two forms:
- pass the transaction directly for methods that only take transactional options, such as
Post.create(data, transaction) - pass it inside an options object for query methods, such as
Post.findAll({ where: { id: 1 }, transaction })
Instance methods also accept transactions:
import { ConnectionManager } from 'morphis'
const transaction = await ConnectionManager.getTransaction()
try {
const post = await Post.findByPk(1, { transaction })
if (post) {
await post.update({ content: 'edited' }, transaction)
await post.destroy({ transaction })
}
await transaction.commit()
} catch (error) {
await transaction.rollback()
throw error
}Transaction notes
- use
await ConnectionManager.getTransaction()to create a transaction on the default connection - use
await ConnectionManager.getTransaction('analytics')to target a named connection - the same transaction can be shared across multiple models and tables as long as those models use the same connection
- a transaction from one connection cannot be used with a model on a different connection
- finish the transaction explicitly with
await transaction.commit()orawait transaction.rollback() - transaction-aware CRUD keeps Morphis key normalization between
camelCaseandsnake_case - you can still use raw Drizzle for joins or lower-level query composition when needed
- explicit transactions are not supported for Cloudflare D1 bindings; local D1 via SQLite storage is supported