xiaohongshu
xiaohongshu
implementing-query-pagination
Implement cursor-based or offset pagination for Prisma queries. Use for datasets 100k+, APIs with page navigation, or infinite scroll/pagination mentions.
Full skill instructions
Teaches correct Prisma 6 pagination patterns with guidance on cursor vs offset trade-offs and performance implications.
<role> Implement cursor-based or offset-based Prisma pagination strategies, choosing based on dataset size, access patterns, and performance requirements. </role> <when-to-activate> Activates when: user mentions "pagination," "page," "infinite scroll," "load more"; building APIs with page navigation/list endpoints; optimizing large datasets (100k+) or slow queries; implementing table/feed views. </when-to-activate> <overview> **Cursor-based pagination** (recommended): Stable performance regardless of size; efficient for infinite scroll; handles real-time changes gracefully; requires unique sequential ordering field.Offset-based pagination: Simple; supports arbitrary page jumps; degrades significantly on large datasets (100k+); prone to duplicates/gaps during changes.
**Core principle: Default to cursor. Use offset only for
small (<10k), static datasets requiring arbitrary page access.** </overview>
<workflow> ## Pagination Strategy WorkflowPhase 1: Choose Strategy
Phase 2: Implement
Phase 3: Optimize & Validate
| Criterion | Cursor | Offset | Winner |
|---|---|---|---|
| Dataset > 100k | Stable O(n) | O(skip+n) | Cursor |
| Infinite scroll | Natural | Poor | Cursor |
| Page controls (1,2,3...) | Workaround needed | Natural | Offset |
| Jump to page N | Not supported | Supported | Offset |
| Real-time data | No duplicates | Duplicates/gaps | Cursor |
| Total count needed | Extra query | Same query | Offset |
| Complexity | Medium | Low | Offset |
| Mobile feed | Natural | Poor | Cursor |
| Admin table (<10k) | Overkill | Simple | Offset |
| Search results | Good | Acceptable | Cursor |
Guidelines: (1) Default cursor for user-facing lists; (2) Use offset only for small admin tables, total-count requirements, or arbitrary page jumping in internal tools; (3) Never use offset for feeds, timelines, >100k datasets, infinite scroll, real-time data. </decision-matrix>
<cursor-pagination> ## Cursor-Based PaginationCursor pagination uses a pointer to a specific record as the starting point for the next page.
async function getPosts(cursor?: string, pageSize: number = 20) {
const posts = await prisma.post.findMany({
take: pageSize,
skip: cursor ? 1 : 0,
cursor: cursor ? { id: cursor } : undefined,
orderBy: { id: 'asc' },
});
return {
data: posts,
nextCursor: posts.length === pageSize ? posts[posts.length - 1].id : null,
};
}
For non-unique fields (createdAt, score), combine with unique field:
async function getPostsByDate(cursor?: { createdAt: Date; id: string }, pageSize: number = 20) {
const posts = await prisma.post.findMany({
take: pageSize,
skip: cursor ? 1 : 0,
cursor: cursor ? { createdAt_id: cursor } : undefined,
orderBy: [{ createdAt: 'desc' }, { id: 'asc' }],
});
const lastPost = posts[posts.length - 1];
return {
data: posts,
nextCursor:
posts.length === pageSize ? { createdAt: lastPost.createdAt, id: lastPost.id } : null,
};
}
Schema requirement:
model Post {
id String @id @default(cuid())
createdAt DateTime @default(now())
@@index([createdAt, id])
}
</cursor-pagination>
<offset-pagination> ## Offset-Based PaginationOffset pagination skips a numeric offset of records.
async function getPostsPaged(page: number = 1, pageSize: number = 20) {
const skip = (page - 1) * pageSize;
const [posts, total] = await Promise.all([
prisma.post.findMany({ skip, take: pageSize, orderBy: { createdAt: 'desc' } }),
prisma.post.count(),
]);
return {
data: posts,
pagination: { page, pageSize, totalPages: Math.ceil(total / pageSize), totalRecords: total },
};
}
Complexity: Page 1 O(pageSize); Page N O(N×pageSize)—linear degradation
Real-world example (1M records, pageSize 20):
Database must scan and discard skipped rows despite indexes.
Use only when: (1) dataset <10k OR deep pages rare; (2) arbitrary page access required; (3) total count needed; (4) infrequent data changes. Common cases: admin tables, search results (rarely past page 5), static archives. </offset-pagination>
<validation> ## ValidationIndex verification: Schema has index on ordering field(s); for cursor use @@index([field1, field2]); run npx prisma format
Performance testing:
console.time('First page');
await getPosts(undefined, 20);
console.timeEnd('First page');
console.time('Page 100');
await getPosts(cursor100, 20);
console.timeEnd('Page 100');
Cursor: both ~similar (5–50ms); Offset: verify acceptable for your use case
Edge cases: first page, last page (<pageSize results), empty results, invalid cursor/page, concurrent modifications
API contract: response includes pagination metadata; nextCursor null when done; hasMore accurate; page numbers
validated (>0); consistent ordering across pages; unique fields in composite cursors </validation>
<constraints> **MUST**: Index cursor field(s); validate pageSize (max 100); handle empty results; return pagination metadata; use consistent ordering; include unique fields in composite cursorsSHOULD: Default cursor for user-facing lists; limit offset to <100k datasets; document pagination strategy; test realistic sizes; consider caching total count
NEVER: Use offset for >100k datasets, infinite scroll, feeds/timelines, real-time data; omit indexes; allow unlimited pageSize; use non-unique sole cursor; modify ordering between requests </constraints>
xiaohongshu
technical spec
product ux expert
database patterns
Conduct multi-agent task orchestration and workflow coordination.
Initialize project with Conductor artifacts (product definition,
Expert in web animations, transitions, and motion design using Framer Motion and CSS
Creates Mermaid and ASCII diagrams for flowcharts, architecture, ERDs, state machines, mindmaps, and more. Use when user mentions diagram, flowchart, mermaid, ASCII diagram, text diagram, terminal diagram, visualize, C4, mindmap, architecture diagram, sequence diagram, ERD, or needs visual docume...
PostgreSQL bindings for H3 hexagonal grid system. Use when working with H3 cells in Postgres, including spatial indexing, geometry/geography integration, and raster analysis.
Context-Driven Development skill for projects using Conductor. Use this skill when you detect a `conductor/` directory in the project, when working on tasks defined in a `plan.md` file, or when the user asks about tracks, specs, or plans. Automatically applies TDD workflow, tracks task completion...
Display project status, active tracks, and next actions
Official Stakpak application containerization standard operating procedure, a step-by-step guidline to properly dockerize applications. This is a rule book curated by the Stakpak Team.
Generate, edit, and beat-sync AI video with leading models in one workspace.
The world's fastest calendar for remote work
Transform Your Design with AI Designer by ImgCreator.ai
Revolutionizing Video Production with AI-Powered Creativity
Extend an image past the frame and let AI fill the new aspect ratio.
Discover your celebrity doppelgänger with StarByFace!
ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.
Opus.ai: Revolutionize Your Web Experience