Skip to content

[FEATURE]: bigint string mode (works with identity + relations) #4990

@mvanwel

Description

@mvanwel

Feature hasn't been suggested before.

  • I have verified this feature I'm about to request hasn't been suggested before.

Describe the enhancement you want to request

Context / prior discussion: #2625

Problem

Drizzle’s Postgres bigint() currently supports mode: 'number' | 'bigint', but not a string mode. Many ecosystems (Discord snowflakes, some external APIs, JSON pipelines) treat 64-bit IDs as strings to avoid precision issues and BigInt JSON pitfalls. Today the only workaround is a customType that converts to/from BigInt, but that breaks/limits ergonomics: you can’t use .generated…AsIdentity() on a customType, and relations are fragile/missing with custom types.

My minimal workaround (works, but limited)

export const bigint = customType<{
  data: string;
  driverData: string | number | bigint;
}>({
  dataType: () => 'bigint',
  toDriver: (v) => {
    if (typeof v !== 'string' || !/^-?\d+$/.test(v)) {
      throw new Error(`Invalid bigint string: ${v}`);
    }
    return BigInt(v);
  },
  fromDriver: (v) => (typeof v === 'string' ? v : v.toString()),
});

Limitations: cannot combine with .generatedAlwaysAsIdentity() / .generatedByDefaultAsIdentity() and doesn’t integrate cleanly with relations.

Requested feature
Add a third mode for Postgres bigint/bigserial/identity columns:

id: bigint({ mode: 'string' }).primaryKey().generatedAlwaysAsIdentity();

What “string mode” should do

  • DB type: still BIGINT in Postgres.
  • TS types: select -> string, insert -> string | undefined (depending on identity).
  • Driver mapping: automatic stringBigInt conversion similar to the customType above (internally), so users don’t touch BigInt at all.
  • Works with: .generatedAlwaysAsIdentity() and (if/when supported) .generatedByDefaultAsIdentity(); sequence options remain available.
  • Relations: first-class support in relations/foreign keys (no “customType” edge cases).

Why this is valuable

  • Avoids precision issues and BigInt JSON serialization errors in common stacks.
  • Matches how many APIs represent 64-bit IDs (strings).
  • Keeps the great DX of identity columns and relations—without customType foot-guns

Backward compatibility

  • Non-breaking: add string alongside existing number | bigint ; current behavior stays default.
  • Docs: a short note in PostgreSQL -> bigint explaining when to pick string (JSON/web APIs), vs number (≤ 2^53), vs bigint (native bigint).

Thanks! This would remove a common friction point when integrating with external APIs while preserving Drizzle’s type-safety and identity ergonomics.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions