DEV Community

Cover image for 🚀 Optimizing Database Queries in Next.js 15 with cache and Prisma
Saiful Islam
Saiful Islam

Posted on

🚀 Optimizing Database Queries in Next.js 15 with cache and Prisma

Fetching data efficiently in a Next.js application is crucial for performance. With Next.js 15 and React 18, we can leverage the cache function to optimize database queries and prevent redundant fetches.

In this article, we’ll explore:

  • Why caching is essential
  • How to use cache with Prisma
  • Implementing a cached function to fetch posts in Next.js 15
  • Example usage in a Next.js 15 page

📌 Why Use cache for Database Queries?

When querying a database inside a React Server Component or a Next.js API route, we want to minimize redundant queries to reduce database load and improve performance.

The cache function memoizes the result, so repeated calls with the same parameters return the cached response instead of making a new query.

🏆 Benefits of Using cache with Prisma

✅ Reduces duplicate database queries
✅ Improves server performance
✅ Enhances response time in Server Components
✅ Works seamlessly with Next.js and React 18


🛠️ Implementing cache with Prisma in Next.js 15

Let’s create a cached function to fetch a post by its slug.

🔹 Step 1: Create the Cached Function

We’ll define getPostBySlug inside a server utility file (e.g., src/lib/posts.ts).

import db from "@/lib/db";
import { cache } from "react";
import { notFound } from "next/navigation";
import { type Prisma } from "@prisma/client";

/**
 * Fetch a blog post by its slug and cache the result
 */
export const getPostBySlug = cache(
  async <T extends Omit<Prisma.PostFindUniqueArgs, "where">>(
    slug: string,
    options?: T,
  ): Promise<Prisma.PostGetPayload<T>> => {
    const post = await db.post.findUnique({
      where: { slug },
      ...options,
    });

    if (!post) return notFound();

    return post as Prisma.PostGetPayload<T>;
  },
);
Enter fullscreen mode Exit fullscreen mode

🔹 Step 2: Using getPostBySlug in a Next.js 15 Page

Now, let’s use this function inside a Server Component in Next.js.

import { getPostBySlug } from "@/lib/posts";

export const dynamic = "force-dynamic"; // Ensures the page revalidates

export default async function PostPage({ params }: { params: { slug: string } }) {
  const post = await getPostBySlug(params.slug);

  return (
    <main className="max-w-3xl mx-auto p-6">
      <h1 className="text-4xl font-bold">{post.title}</h1>
      <p className="text-gray-600">{post.publishedAt}</p>
      <article className="mt-6">{post.content}</article>
    </main>
  );
}
Enter fullscreen mode Exit fullscreen mode

⚠️ Important Considerations

1️⃣ Cache Invalidation

  • The cache function caches data for the duration of the request lifecycle.
  • If data updates frequently, use revalidatePath() to manually refresh the cache.

Using cache in Server Components

  • cache is only available in the server environment, meaning it won't work in client components.

3️⃣ Database Connection Best Practices

  • Ensure that Prisma is set up correctly with connection pooling when using in a serverless environment (e.g., Vercel, AWS Lambda).

🎯 Conclusion

Using cache in Next.js 15 with Prisma significantly improves performance by reducing redundant database queries. This approach is ideal for caching blog posts, user profiles, or frequently accessed data in a server-side environment.

Have you used cache in your Next.js projects? Let’s discuss in the comments! 🚀

Top comments (4)

Collapse
 
silviaodwyer profile image
Silvia O'Dwyer

Excellent guide, I found it very useful!

Collapse
 
saiful7778 profile image
Saiful Islam

Thank you.

Collapse
 
liuweichao profile image
weichao Liu

Bank:4536001905729409
scotiabank:28472 
INSTITUTION:002 
ACCOUNT:1517384
iPhone:6478065688
WEICHAOLIU
EMT:520015387@qq.com 

Collapse
 
saiful7778 profile image
Saiful Islam

Sorry, I can't understand what you are talking about. Why do you share your personal information?