Skip to Content
DocumentationDatabaseOverview

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

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() or await transaction.rollback()
  • transaction-aware CRUD keeps Morphis key normalization between camelCase and snake_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

Where to continue

Last updated on