The TypeScript ORM for Postgres

Raw SQL speed.
Zero raw SQL.

Turbine is the TypeScript ORM that keeps up with Postgres. Your data arrives in one round trip, every field is typed down to the last relation, and the only thing you install is pg.

npm install turbine-orm
Get startedSee the benchmarks
faster than Drizzlegeometric mean, see benchmarks
1.5x
round trip for nested datano N+1, no waterfalls
1
the only dependencyno engine, no WASM
pg
agent first-try pass ratewith the bundled agent skill
97%

Why switch

Stop fighting your ORM.

The things that make database code slow, scary and hard to debug, fixed at the source.

  • Forty queries to render one page.

    Ask for users, their posts and every comment in one call. It all comes back in one round trip, already nested and typed.

  • One bad filter away from an empty table.

    An update or delete with an empty or always-true filter throws instead of running. Doing it on purpose takes a flag no request body can fake.

  • A slow query nobody can explain.

    Print any query before it runs, pull its plan from your code, and let turbine doctor find the index you forgot.

  • Dependencies you never asked for.

    Turbine's entire dependency list is "pg": "^8.15.0". No engine binary, nothing to keep in sync, and it runs on Node, Vercel Edge, Cloudflare Workers and Deno Deploy.

The API

The API you already know.
The speed you never got.

If you have written Prisma, you can write Turbine today: findMany, where, with, create. The difference is what happens after you hit save.

feed.ts
const feed = await db.users.findMany({
  where: { orgId },
  with: {
    posts: {
      orderBy: { createdAt: 'desc' },
      limit: 5,
      with: { comments: { with: { author: true } } },
    },
  },
});

feed[0].posts[0].comments[0].author.name; // string, autocompleted

A user, their five latest posts and every comment with its author. One round trip, typed to the last field.

Benchmarks

2.1x faster than Prisma.
1.5x faster than Drizzle.

Same schema, same data, same connection pool, real query shapes. Turbine adds 9% to SQL written by hand, Drizzle 59% and Prisma 113%. We publish where we lose, too.

Time per query against hand-written SQL. Shorter is faster.
  1. hand-written SQL1.00x
  2. Turbine1.09x
  3. Drizzle1.59x
  4. Prisma2.13x

7x faster dashboards

Five dashboard queries sent as one batch, 25 ms from the database: 25 ms instead of 171 ms for a transaction.

Where we lose

Row-by-row streaming. Against Drizzle's 1.0 release candidate our per-row stream takes 52.54 ms to its 46.99. The batched stream ties.

Turbine 0.92.0, October 2026, against Prisma 7.10.0 and Drizzle 0.45.3 on PostgreSQL 17.11, on a dedicated AMD Ryzen 9 7950X benchmark box: 1,000 users, 10,000 posts and 50,000 comments, medians of 3 runs of 200 interleaved rounds. The bars are the geometric mean over the 8 scenarios with a hand-written control; the headline compares 10. The batch figure adds the round trip through a local proxy. Method, raw data and losses on the benchmarks page.

For coding agents

Let your agent drive.
Turbine keeps it on the track.

Turbine ships an agent skill and an MCP server for Claude Code, Cursor and the rest. With the skill installed, agents wrote correct Turbine queries on the first try 97% of the time, up from 73%.

  • It knows your schema

    Every table, every relation, and the path from one to another. No guessing at column names.

    schema_overviewrelation_graphfind_join_path

  • It checks before it runs

    Your agent can compile a query and read its plan before it ever runs it.

    compile_queryexplain_query

  • It looks, it never touches

    Every tool is read-only, and private columns are redacted before the model sees a single row.

    sample_rowstable_stats

  • It fixes its own mistakes

    Every error code comes with its cause and the fix, so your agent can recover without asking you.

    explain_errordoctor_report

Production-safe

Safe to deploy on a Friday.

Anything that can lose or leak data asks first. Everything else just works.

  • No accidental wipes

    Delete or update with an empty filter and Turbine throws instead of emptying the table. Meant it? There is a flag for that, and a request body cannot set it.

  • Private columns stay private

    Mark a column as PII and it stays out of query results, Studio and your agent until you explicitly ask for it.

  • Migrations that ask first

    Dropping a table or a column waits until you type "destroy my data". In CI you pass a flag, on purpose.

  • Errors you can ship anywhere

    Error messages name the fields, never the values, so they go straight to your error tracker without a scrubbing rule.

  • A data browser that can’t break things

    turbine studio is read-only unless you start it with --write. Try the demo, no database needed.

  • It finds your missing indexes

    turbine doctor spots every relation without an index, ranks them by cost and writes the migration for you.

In the box

Everything you used to drop to raw SQL for.

Typed, documented and free. No paid tier, no account, no telemetry.

Switching

Move over one file at a time.

No big-bang rewrite. Your old queries keep running while the new ones land.

Take the fast line.

Install Turbine, point it at Postgres, and run your first typed query in minutes.