Best Practices
Conventions for predictable, production-ready apps using Drizzleasy.
Architecture
- Prefer server actions for mutations; read on the server for SSR/SSG
- Avoid creating separate REST routes when you can call server actions directly
- Do not access the database on the client
Coding style (TypeScript + Next.js)
- Prefer pure functions and immutable data for predictability
- Type everything (entities, inputs, results)
- Consider named exports (common in libraries); Next.js pages/views can be default exports
- Keep complex UI state in reducers; keep reducers pure
- Organize server actions close to the domain they modify
Server actions
'use server'
import { createFn, updateFn, readFn, destroyFn } from '@remcostoeten/drizzleasy'
type TUser = { id: string; email: string; name: string; status: 'active' | 'inactive' }
export async function createUser(data: { email: string; name: string }) {
const create = createFn<TUser>()
return create('users')({ id: crypto.randomUUID(), email: data.email, name: data.name, status: 'active' })
}
export async function getUsers() {
const read = readFn<TUser>()
return read('users')()
}Error handling
- Use the provided
DrizzleasyErrorclasses for consistent error surfaces - Wrap async work with
handleAsyncErrorand log withlogError
Performance
- Wrap critical operations with
measurePerformance - Index columns used in WHERE conditions
- Reuse connections;
initializeConnectioncaches connections
Environment
- Validate env with
validateDatabaseEnvironment - Provide
TURSO_AUTH_TOKENfor libsql - Use environment switching config for development vs production