Oscar te Giffel®
← Writing

Moving to Drizzle and back.

I tried switching from Prisma to Drizzle. Many-to-many relationships sent me right back.

I’m always trying new tools. It’s part of the job and honestly I just enjoy it. So when Drizzle started getting traction as a lighter alternative to Prisma, I figured I’d give it a shot.

My requirements for an ORM are pretty simple: good DX, a clean API for queries and mutations, and solid TypeScript support. Drizzle fell short on one specific use case that killed it for me.

Here’s a simple schema with users and groups:

export const users = mysqlTable("users", {
  id: varchar("id", { length: 256 }).primaryKey(),
  name: varchar("name", { length: 256 }).notNull(),
});

export const groups = mysqlTable("groups", {
  id: varchar("id", { length: 256 }).primaryKey(),
  name: varchar("name", { length: 256 }).notNull(),
});

I’m using varchar for the id type and generating UUIDs in the application. This avoids issues with MySQL’s LAST_INSERT_ID() in serverless environments.

For a many-to-many relationship you have to manually create the junction table in Drizzle:

export const usersToGroups = mysqlTable(
  "users_to_groups",
  {
    userId: varchar("user_id")
      .notNull()
      .references(() => users.id),
    groupId: varchar("group_id")
      .notNull()
      .references(() => groups.id),
  },
  (t) => ({
    pk: primaryKey(t.userId, t.groupId),
  }),
);

// Relation definitions omitted for brevity

Fine so far. But the API for querying related data is where it gets ugly. Fetching a user with their groups:

await db.query.users.findFirst({
  with: {
    groups: {
      with: {
        group: true,
      },
      where: eq(usersToGroupsRelations.userId, input.id),
    },
  },
  where: eq(usersToGroupsRelations.id, input.id),
});

And the resulting data structure is just as messy:

{
  "id": "XRdUD20AfH422nXKI72HW",
  "name": "test",
  "groups": [
    {
      "userId": "XRdUD20AfH422nXKI72HW",
      "groupId": "_VQnVW4cZj4HvnCC1W9Lr",
      "group": {
        "id": "_VQnVW4cZj4HvnCC1W9Lr",
        "name": "sdf",
        "description": "sdf",
        "quantity": 0,
        "unit": "kg"
      }
    }
  ]
}

That nested groups[0].group structure is not something I want to deal with across an entire codebase. Back to Prisma it was.

Drizzle might work well for simpler schemas or if you prefer staying close to SQL. But for relational queries with any complexity, Prisma’s API is just better. Sometimes the grass isn’t greener.