Connections
Database connections are defined in src/config/database.ts. Each connection needs a driver plus the driver-specific connection fields.
Morphis resolves the default connection like this:
- the entry with
isDefault: true, or - the first connection in the exported object
File shape
Use defineDatabases so your connection names stay typed.
import { defineDatabases, type DatabaseName } from 'morphis'
const databases = defineDatabases({
default: {
isDefault: true,
driver: 'sqlite',
connection: {
storage: './database.sqlite',
},
},
})
export type ConnectionName = DatabaseName<typeof databases>
export default databasesRequired config by driver
Postgres
import { defineDatabases } from 'morphis'
export default defineDatabases({
default: {
isDefault: true,
driver: 'postgres',
connection: {
host: process.env.DB_HOST || '127.0.0.1',
port: Number(process.env.DB_PORT || 5432),
database: process.env.DB_NAME || 'app',
username: process.env.DB_USERNAME || 'postgres',
password: process.env.DB_PASSWORD || '',
},
},
})Needs:
hostportoptional but recommendeddatabaseusernamepassword
MySQL
import { defineDatabases } from 'morphis'
export default defineDatabases({
default: {
isDefault: true,
driver: 'mysql',
connection: {
host: process.env.DB_HOST || '127.0.0.1',
port: Number(process.env.DB_PORT || 3306),
database: process.env.DB_NAME || 'app',
username: process.env.DB_USERNAME || 'root',
password: process.env.DB_PASSWORD || '',
},
},
})Needs the same fields as Postgres.
MariaDB
import { defineDatabases } from 'morphis'
export default defineDatabases({
default: {
isDefault: true,
driver: 'mariadb',
connection: {
host: process.env.DB_HOST || '127.0.0.1',
port: Number(process.env.DB_PORT || 3306),
database: process.env.DB_NAME || 'app',
username: process.env.DB_USERNAME || 'root',
password: process.env.DB_PASSWORD || '',
},
},
})MSSQL
import { defineDatabases } from 'morphis'
export default defineDatabases({
default: {
isDefault: true,
driver: 'mssql',
connection: {
host: process.env.DB_HOST || '127.0.0.1',
port: Number(process.env.DB_PORT || 1433),
database: process.env.DB_NAME || 'app',
username: process.env.DB_USERNAME || 'sa',
password: process.env.DB_PASSWORD || '',
},
},
})SQLite
import { defineDatabases } from 'morphis'
export default defineDatabases({
default: {
isDefault: true,
driver: 'sqlite',
connection: {
storage: process.env.DB_STORAGE || './database.sqlite',
},
},
})Needs:
storage: local SQLite file path
D1
This is the most important one to configure correctly because it has both a Cloudflare runtime mode and a local Bun fallback mode.
import { defineDatabases, type DatabaseName } from 'morphis'
const localStorage = process.env.DB_STORAGE || './database.sqlite'
const binding = process.env.CLOUDFLARE_D1_BINDING || process.env.D1_BINDING || 'DB'
const databases = defineDatabases({
default: {
isDefault: true,
driver: 'd1',
connection: {
// Remote Cloudflare Worker uses the D1 binding.
binding,
// Local Bun development falls back to the SQLite file.
storage: localStorage,
},
},
})
export type ConnectionName = DatabaseName<typeof databases>
export default databasesNeeds:
bindingfor Cloudflare runtime accessstoragefor local Bun development and local migration support
Optional at runtime:
databaseif you inject a D1 object directly instead of resolving a binding
How D1 resolution works
For a d1 connection, Morphis resolves the database in this order:
connection.database- a global runtime binding matching
connection.binding connection.storageas a local SQLite fallback when running under Bun
If you deploy to Cloudflare and the binding is missing, the connection will fail at runtime.
D1 support
Morphis resolves a D1 database from a direct connection object, a named runtime binding, or a local storage fallback when running under Bun.
Cloudflare D1 deployment
When Morphis detects a D1 connection during Cloudflare deployment, it deploys as a Worker so the D1 binding is available at runtime.
To link the deployed Worker to the remote D1 database, make sure these values are available in your env file or CLI flags:
CLOUDFLARE_D1_BINDINGorD1_BINDINGCLOUDFLARE_D1_DATABASE_NAMEorD1_DATABASE_NAMECLOUDFLARE_D1_DATABASE_IDorD1_DATABASE_ID
Example env values:
CLOUDFLARE_D1_BINDING=DB
CLOUDFLARE_D1_DATABASE_NAME=my-production-db
CLOUDFLARE_D1_DATABASE_ID=12345678-1234-1234-1234-123456789abc
DB_STORAGE=./database.sqliteExample deploy command:
morphis deploy --target=cloudflare --server=apiOr pass the remote database identifiers directly:
morphis deploy --target=cloudflare --server=api --d1-binding=DB --d1-name=my-production-db --d1-id=12345678-1234-1234-1234-123456789abcDuring deployment, Morphis generates a temporary Wrangler config with a [[d1_databases]] block that links the Worker binding to the remote D1 database. The binding name must match the one your src/config/database.ts expects.
Good practice
Keep the default connection stable, keep local and remote D1 settings in the same connection definition, and only add extra named connections when you really need separate databases.