Exercise 1: Posts Per Month — Possible Solution ================================================= type MonthRow = { month: number; posts: number }; app.get("/stats/monthly", async (req, res) => { const year = new Date().getFullYear(); const start = new Date(year, 0, 1); const end = new Date(year + 1, 0, 1); const rows = await prisma.$queryRaw` SELECT EXTRACT(MONTH FROM "createdAt")::int AS "month", COUNT(*)::int AS "posts" FROM "Post" WHERE "published" = true AND "createdAt" >= ${start} AND "createdAt" < ${end} GROUP BY 1 ORDER BY 1 `; res.json(rows); }); $ curl localhost:3000/stats/monthly [{"month":3,"posts":2},{"month":6,"posts":5},{"month":9,"posts":4}] The alternative fix, if you'd rather not cast in SQL: res.json(rows.map((r) => ({ month: Number(r.month), posts: Number(r.posts) }))); WHY THIS WORKS AS AN ANSWER ------------------------------ Grouping by month isn't something Prisma Client's groupBy can do — it groups by stored fields, not by values computed from them — so raw SQL is the right tool. The dates are passed as parameters, not pasted into the SQL. On PostgreSQL COUNT(*) returns bigint (and EXTRACT returns a numeric), which would reach JavaScript as bigint/Decimal; the ::int casts turn them into plain numbers, so res.json works. Using a start/end range instead of EXTRACT(YEAR ...) in WHERE also lets the database use an index on createdAt.