Search docs

Jump between documentation pages.

Use AWS Aurora DSQL with DaloyJS

Aurora DSQL is AWS's serverless, distributed PostgreSQL service. It speaks the Postgres wire protocol, so you use the standard pg driver — but auth is short-lived IAM tokens instead of a static password. Pair it with the Lambda adapter for a fully managed AWS-native stack.

1. Provision a cluster

Create a cluster in the AWS console or via the CLI. Note the endpoint hostname and the AWS region.

ts
aws dsql create-cluster --region us-east-1

2. Install

ts
pnpm add pg @aws-sdk/dsql-signer

3. Generate a token and connect

DSQL tokens expire (default ~15 minutes), so build a connection helper that refreshes the password before opening a connection. For Lambda, create one client per invocation; for long-lived Node processes, refresh on a timer or on auth errors.

ts
// src/db/dsql.ts
import { Client } from "pg";
import { DsqlSigner } from "@aws-sdk/dsql-signer";

const signer = new DsqlSigner({
  hostname: process.env.DSQL_ENDPOINT!,
  region: process.env.AWS_REGION ?? "us-east-1",
});

export async function createDsqlClient() {
  const token = await signer.getDbConnectAdminAuthToken();
  const client = new Client({
    host: process.env.DSQL_ENDPOINT!,
    port: 5432,
    user: "admin",
    password: token,
    database: "postgres",
    ssl: { rejectUnauthorized: true },
  });
  await client.connect();
  return client;
}

4. Plugin pattern (long-lived Node)

ts
// src/db/plugin.ts
import type { App } from "@daloyjs/core";
import { createDsqlClient } from "./dsql";

export const dsqlPlugin = {
  name: "dsql",
  async register(app: App) {
    const client = await createDsqlClient();
    app.decorate("db", client);
    app.onClose(async () => {
      await client.end();
    });
  },
};

5. Lambda pattern (per-invocation)

On the Lambda adapter, create the client inside the handler and close it at the end so the IAM token doesn't expire between cold starts:

ts
import { toLambdaHandler } from "@daloyjs/core/lambda";
import { createDsqlClient } from "./db/dsql";

const daloyHandler = toLambdaHandler(app);

export const handler = async (event) => {
  const db = await createDsqlClient();
  app.decorate("db", db);
  try {
    return await daloyHandler(event);
  } finally {
    await db.end();
  }
};

6. Augment app state

ts
// src/types/state.d.ts
import type { Client } from "pg";

declare module "@daloyjs/core" {
  interface AppState {
    db: Client;
  }
}

With Drizzle ORM

ts
pnpm add drizzle-orm
// src/db/drizzle.ts
import { drizzle } from "drizzle-orm/node-postgres";
import { createDsqlClient } from "./dsql";

export async function createDb() {
  const client = await createDsqlClient();
  return drizzle({ client });
}

With Prisma

Use the pg Driver Adapter and inject a Postgres connection that uses the IAM token. The same caveats as above apply: tokens expire, so refresh per Lambda invocation.

Things to remember

  • DSQL is TCP-only, so it does not work on Cloudflare Workers or Vercel Edge. Use Neon or PlanetScale there.
  • IAM tokens expire — refresh on every Lambda invocation, or wrap re-connection logic around long-lived Node processes.
  • DSQL has Postgres-compatible semantics but not 100% feature parity. Check the known issues before relying on niche extensions.

See also the database hosting overview or jump back to Prisma / Drizzle.