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
Principles
Tooling & Workspace
Workspace Overview
Cli
Jobs & Commands
SDK
Error Handling
Extensions
Typescript
Go
Python
Docker
Ci
Frameworks
Typescript
OverviewWebReact RoutingForms And ActionsStatic FilesApiErrors And ResponsesConfigurationLoggingHttp And MiddlewareDependency InjectionPlugins And LifecycleSessionsAuthPersistenceEventsStorageCachingWebsocketsTestingHealth ChecksTelemetryProto GrpcSmart Client
Go
OverviewHttpDependency InjectionPlugins And LifecycleConfigurationSecurityPersistenceErrorsEventsStorageCachingLoggingTelemetryGrpcService ClientsValidationOpenapiTesting
Platform
  1. DocsSeparator
  2. How ToSeparator
  3. Add Persistence

Add persistence

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

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

Steps

1) Add SQL + configure a database

bunx putnami deps add @putnami/sql

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/sql';
import type { InferTable } from '@putnami/sql';

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/sql';

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.

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