npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@aws/aurora-dsql-drizzle

v0.1.0

Published

Drizzle ORM adapter for Amazon Aurora DSQL

Readme

Aurora DSQL adapter for Drizzle ORM

GitHub npm version License Discord chat

Drizzle ORM support for Amazon Aurora DSQL.

It rides on drizzle-orm/node-postgres: the Aurora DSQL connector is a pg.Pool with IAM token authentication, so there is no custom dialect — just a thin drizzle() factory, an opt-in OCC retry helper, a DSQL-aware migrator, and a migration CLI.

Requirements

  • Drizzle ORM ^0.45 and pg >=8 (peer dependencies)
  • Node.js >=20
  • An Aurora DSQL cluster, and AWS credentials with dsql:DbConnect for the database role you connect as

Install

npm install @aws/aurora-dsql-drizzle drizzle-orm pg
npm install -D drizzle-kit

IAM authentication and TLS are handled by the connector.

Connect

import { drizzle } from "@aws/aurora-dsql-drizzle";
import * as schema from "./schema";

const db = drizzle({
  connection: {
    host: process.env.CLUSTER_ENDPOINT!, // <id>.dsql.<region>.on.aws
    region: "us-east-1", // optional; inferred from the host otherwise
    user: "myuser", // a database role scoped to what your app needs
    options: "-c search_path=myschema",
  },
  schema,
});

const owners = await db.select().from(schema.owner);

user is required — see Using database roles and IAM authentication for creating a role granted only the privileges your application needs. There is no default, so a connection never lands on admin by omission.

Already have a pool? Pass it directly: drizzle({ client: pool, schema }), where pool is an AuroraDSQLPool (or any pg.Pool). db.$client exposes the underlying pool; call await db.$client.end() to close it.

Transactions with OCC retry

DSQL uses optimistic concurrency control: conflicting transactions fail at COMMIT with OC000 / OC001 (SQLSTATE 40001). db.transactionWithRetry re-runs the whole transaction on those conflicts.

import { sql } from "drizzle-orm";

await db.transactionWithRetry(async (tx) => {
  await tx.update(accounts).set({ balance: sql`balance - 100` }).where(...);
  await tx.update(accounts).set({ balance: sql`balance + 100` }).where(...);
});

The callback is re-run on every retry, so it must be idempotent — no side effects (emails, queue writes) that must not repeat. Keep transactions flat: a nested tx.transaction() fails fast with an explanatory error, so partial work is never mistaken for a committed savepoint.

Retry defaults are maxRetries 3, baseDelayMs 50, maxDelayMs 5000 (exponential backoff with equal jitter). Pass an optional transaction config second and retry overrides third; when retries are exhausted it throws AwsDsqlRetryExhaustedError (the last conflict is on .cause).

await db.transactionWithRetry(
  async (tx) => { await tx.insert(orders).values({ ... }); },
  { isolationLevel: "serializable" },
  { maxRetries: 5, onRetry: (err, attempt, max) => log.warn({ err, attempt, max }) },
);

Migrations

Import migrate from this package. It applies one DDL statement per transaction — matching how DSQL runs DDL — and tracks each statement individually, so use it in place of the stock drizzle-orm/node-postgres migrator, which sends every statement in a single transaction:

import { migrate, getMigrationStatus } from "@aws/aurora-dsql-drizzle";

const result = await migrate(db, { migrationsFolder: "./drizzle" });
if (!result.success) throw new Error(result.error.message);

The workflow is:

  1. Generate SQL from your schema and rewrite it for DSQL:

    npx aurora-dsql-drizzle generate --out ./drizzle -- --config drizzle.config.ts

    This runs drizzle-kit generate, then rewrites each statement with dsql-lint — the Aurora DSQL linter and fixer — while preserving Drizzle's --> statement-breakpoint markers. It turns CREATE INDEX into CREATE INDEX ASYNC, rewrites SERIAL columns as BIGINT … GENERATED … AS IDENTITY (a type widening — review it), removes foreign-key constraints, and reports anything it cannot rewrite. Review and commit the result. (transform and lint subcommands run those steps on their own.)

    Keep Drizzle Kit's breakpoints: true (the default). The adapter applies one statement per marker, so a breakpoint-free file holding more than one statement is rejected with an explanatory error rather than sent as a single multi-statement transaction.

    Known limitation: the transform lints each statement separately, so a fix needing more than one statement at a time does not apply. The case to know about is ALTER COLUMN … ADD GENERATED … AS IDENTITY, which dsql-lint folds into the preceding CREATE TABLE when it sees both together; here it sees only the ALTER and reports it as unfixable. Define identity columns in the table definition, or merge the two statements by hand.

  2. Apply the committed migrations at deploy time, using the migrate() call above.

    Each statement is applied on its own (autocommit) and then recorded in a tracking table, so a run interrupted partway resumes where it left off — recorded statements are skipped. Asynchronous DDL (CREATE INDEX ASYNC, ALTER TABLE ASYNC … VALIDATE CONSTRAINT) is awaited before the statement is recorded, so a failed background job is never reported as success. Conflicting statements are retried on DSQL's optimistic-concurrency errors. getMigrationStatus(db, config) reports applied vs. pending without changing anything.

    One caveat on resuming: a statement and its tracking row are separate commits. If a run dies in the gap between them, the statement is applied but untracked, and because drizzle-kit emits CREATE TABLE without IF NOT EXISTS the re-run fails with "already exists". migrate() reports which statement it was so you can reconcile the tracking table by hand.

CLI

aurora-dsql-drizzle generate [--out <dir>] [-- <drizzle-kit args>]   Generate + transform
aurora-dsql-drizzle transform [input] [-o output]                    Transform SQL for DSQL
aurora-dsql-drizzle lint [input]                                      Lint SQL for DSQL

Exit codes: 0 clean, 1 unfixable errors remain (and the adapter's own usage errors, e.g. an unknown flag), 2 usage error propagated from dsql-lint, 3 fixed with advisories (e.g. foreign keys removed — review before applying).

Example

See examples/veterinary-app for a complete project: schema, committed DSQL migration, db:migrate script, and integration tests against a live cluster.

Resources

Security

See CONTRIBUTING for more information.

License

Apache-2.0