Exercise 1: Fixing an N+1 Tags Endpoint — Possible Solution ============================================================== The slow version: app.get("/tags/top-posts", async (req, res) => { const tags = await prisma.tag.findMany(); // 1 query const result = []; for (const tag of tags) { const posts = await prisma.post.findMany({ // 1 query PER TAG where: { published: true, tags: { some: { id: tag.id } } }, orderBy: { viewCount: "desc" }, take: 3, select: { title: true, slug: true }, }); result.push({ tag: tag.name, posts }); } res.json(result); }); With 30 tags, the query log shows 31 statements: one SELECT on "Tag", then the same post SELECT 30 times with a different tag id. The fixed version: app.get("/tags/top-posts", async (req, res) => { const tags = await prisma.tag.findMany({ orderBy: { name: "asc" }, select: { name: true, posts: { where: { published: true }, orderBy: { viewCount: "desc" }, take: 3, select: { title: true, slug: true }, }, }, }); res.json(tags.map((t) => ({ tag: t.name, posts: t.posts }))); }); The log now shows a fixed number of statements (one for the tags and a small, constant number for the related posts), no matter how many tags exist. WHY THIS WORKS AS AN ANSWER ------------------------------ It uses the query log to prove the problem (statements that grow with the number of tags) and to prove the fix (a count that stays the same). The nested select keeps the where, orderBy and take limits inside the relation, so each tag still gets only its top three published posts, and only the two columns the endpoint returns are fetched.