Fix a slow OnMission list without throwing Prisma away

OnMission’s assignment board looked simple in Prisma and expensive in Postgres. Follow these steps on any HR list page that loads more columns than it renders.

OnMission (and LOMA, which uses the same Prisma + Postgres shape) made schema changes easy. The open-assignments endpoint did not. Here is the path I use before I write raw SQL.

Step 1: Keep Prisma on the write path

Creates, updates, and transactions stay in Prisma. Nested writes and typed input beat hand-rolled SQL for employee records.

Step 2: Select only the columns the list paints

If the board shows id, title, and due date, do not include the employee relation tree.

import { prisma } from "../db";

export function listOpenAssignments(orgId: string) {
  return prisma.assignment.findMany({
    where: { orgId, status: "open" },
    select: { id: true, title: true, dueAt: true },
    orderBy: { dueAt: "asc" },
    take: 50,
  });
}

Step 3: Add the index that matches filter + sort

model Assignment {
  id     String   @id @default(cuid())
  orgId  String
  status String
  title  String
  dueAt  DateTime

  @@index([orgId, status, dueAt])
}

Step 4: EXPLAIN the query before you blame the ORM