back
typescript·database

Drizzle ORM Paginated Query

Type-safe cursor-based pagination with Drizzle ORM and PostgreSQL.

#drizzle orm#postgresql#typescript#backend

typescript
import { db } from '@/app/db/drizzle';
import { posts } from '@/app/db/schema';
import { desc, eq, lt } from 'drizzle-orm';

interface PaginateOptions {
  limit?: number;
  cursor?: number; // last seen id
}

export async function getPaginatedPosts({ limit = 10, cursor }: PaginateOptions) {
  const rows = await db
    .select()
    .from(posts)
    .where(
      cursor
        ? lt(posts.id, cursor)   // fetch rows before cursor
        : eq(posts.published, true)
    )
    .orderBy(desc(posts.id))
    .limit(limit + 1);  // fetch one extra to detect next page

  const hasNextPage = rows.length > limit;
  const data = hasNextPage ? rows.slice(0, limit) : rows;
  const nextCursor = hasNextPage ? data[data.length - 1].id : undefined;

  return { data, nextCursor, hasNextPage };
}

more snippets