Putnami
DocsGitHub

Licensed under FSL-1.1-MIT

Getting Started
Concepts
How To
Build A Web App
Build An Api Service
Share Code Between Projects
Configure Your App
Add Persistence
Add Authentication
Add Background Jobs
Develop With Ai
Structure Business Logic With Di
Upgrade Putnami
Principles
Tooling & Workspace
Workspace
Cli
Jobs & Caching
Extensions
Templates
Error Handling
Frameworks
Typescript
ExtensionOverviewWebReact RoutingForms And ActionsStatic FilesApiErrors And ResponsesConfigurationLoggingHttp And MiddlewareDependency InjectionPlugins And LifecycleSessionsAuthPersistenceEventsStorageCachingWebsocketsTestingHealth ChecksTelemetryProto GrpcSmart ClientSchema
Go
ExtensionOverviewHttpDependency InjectionPlugins And LifecycleConfigurationSecurityPersistenceErrorsEventsStorageCachingLoggingTelemetryGrpcService ClientsValidationOpenapiTesting
Python
Extension
Platform
Ci
  1. DocsSeparator
  2. How ToSeparator
  3. Add Persistence

Add persistence

You will add a PostgreSQL-backed feature using @putnami/database with migrations and a repository.

Steps

1) Add SQL + configure a database

bunx putnami deps add @putnami/database

Create .env.local.yaml:

database:
  host: localhost
  port: 5432
  database: myapp
  user: postgres
  password: your_password

2) Define a table + repository

Create apps/web/src/db/user.ts:

import { Table, Column, Key, Uuid, Email, Repository } from '@putnami/database';
import type { InferTable } from '@putnami/database';

const CreateUsersTable = {
  name: '20250101000000-create-users-table',
  sql: `
    CREATE TABLE IF NOT EXISTS users (
      id UUID PRIMARY KEY,
      email VARCHAR(255) UNIQUE NOT NULL,
      name VARCHAR(255) NOT NULL
    );
  `,
};

export const UsersTable = Table('users', {
  id:    Key(Uuid),
  email: Column(Email),
  name:  Column(String),
}, {
  migrations: [CreateUsersTable],
});

export type User = InferTable<typeof UsersTable>;

export class UserRepository extends Repository<typeof UsersTable> {
  constructor() {
    super(UsersTable);
  }
}

3) Enable the SQL plugin

Update apps/web/src/main.ts:

import { application } from '@putnami/application';
import { sql } from '@putnami/database';

export const app = () => application().use(sql());

4) Read and write from a route

Create apps/web/src/app/users/post.ts:

import { endpoint } from '@putnami/application';
import { UserRepository } from '../../db/user';

export default endpoint(async () => {
  const repo = new UserRepository();
  const user = await repo.save({
    id: crypto.randomUUID(),
    email: 'hello@example.com',
    name: 'Hello',
  });
  return { user };
});

Result

You now have an app that persists data.

Companion sample: typescript/samples/06-database — a runnable project with repository pattern, migrations, and transactions. Run putnami serve @example/database from the workspace root.

On this page

  • Add persistence
  • Steps
  • 1) Add SQL + configure a database
  • 2) Define a table + repository
  • 3) Enable the SQL plugin
  • 4) Read and write from a route
  • Result