Prisma IDB FaviconPrisma IDB
CRUD Operations

findUnique

Get a single record by unique identifier

Retrieve a single record by its primary key or unique field.

// By primary key
const user = await client.user.findUnique({
  where: { id: "user-123" },
});

// By unique field
const user = await client.user.findUnique({
  where: { email: "alice@example.com" },
});

Return Type

Returns the record or null if not found:

const user: User | null = await client.user.findUnique({
  where: { id: userId },
});

if (user === null) {
  // Record doesn't exist
}

For error handling, use findUniqueOrThrow.

By Primary Key

Use the @id field:

const user = await client.user.findUnique({
  where: { id: "123" },
});

const todo = await client.todo.findUnique({
  where: { id: "456" },
});

By Unique Field

Use any field marked with @unique:

const user = await client.user.findUnique({
  where: { email: "alice@example.com" },
});

Your Prisma schema determines which fields support unique lookup:

model User {
  id    String  @id
  email String  @unique  // Can use in findUnique
  name  String
}

Composite Unique Keys

For models with @@unique on multiple fields:

model Post {
  id        String  @id
  slug      String
  boardId   String

  @@unique([slug, boardId])  // Composite unique constraint
}

Query using both fields:

const post = await client.post.findUnique({
  where: {
    slug_boardId: {
      // Composite key name
      slug: "hello-world",
      boardId: "board-123",
    },
  },
});

Selection

Control which fields are returned:

const user = await client.user.findUnique({
  where: { id: userId },
  select: { id: true, name: true, email: true },
});

Relations

Include related records:

const user = await client.user.findUnique({
  where: { id: userId },
  include: { profile: true },
});

const userWithTodos = await client.user.findUnique({
  where: { id: userId },
  include: {
    profile: true,
    todos: {
      where: { done: false },
      orderBy: { createdAt: "desc" },
    },
  },
});

Performance

findUnique performs a direct indexed lookup, typically O(log n) in typical B-tree/index implementations:

// ✅ Faster - direct indexed lookup
const user = await client.user.findUnique({
  where: { id: userId }, // Logarithmic via index
});

// ⚠️ May be slower if fields are not indexed
const user = await client.user.findFirst({
  where: { email: "alice@example.com" },
}); // Can be fast with appropriate indexes

Ensure your lookup fields are indexed in your schema for best performance.

Null Handling

const user = await client.user.findUnique({
  where: { id: userId },
});

// Type-safe null check
if (user === null) {
  console.log("User not found");
} else {
  console.log(user.name);
}

// Optional chaining
console.log(user?.name);

Use Cases

User Session

const currentUser = await client.user.findUnique({
  where: { id: sessionUserId },
});

if (!currentUser) {
  redirectToLogin();
}

Resource Access

const todo = await client.todo.findUnique({
  where: { id: todoId },
});

if (!todo) {
  throw new Error("Todo not found");
}

// Verify ownership
if (todo.userId !== currentUserId) {
  throw new Error("Access denied");
}

See Also

On this page