Multi Project (Database) Set-up With Prisma and Neon

Hi all, I am currently investigating a project per user set up for my multi-tenant application which uses Neon, Prisma ORM and Next.js hosted in Vercel. I have played around with the Neon API and was able to create a new project and run migrations on that project as soon as a new user logs in to the application. All good so far. However, I realised one issue at the point where requests are made to my database via Prisma. That is, usually the Prisma Client is only instantiated once and database url is defined once with: datasource db { provider = "postgresql" url = env("DATABASE_URL") } This is a problem as I will have many DATABASE_URL variables with this set up. I think creating new Prisma Client instances for each request is a bad idea. Any advice to get around this? Maybe this is the wrong direction, but Neon makes it so easy and cheap to have a database per user and I would like to pursue it if possible, not least because my particular type of user values data security a lot (more of a peace of mind thing).
1 Reply
Prisma AI Help
Prisma AI Help3mo ago
You opted for speed from this bot. Let's conjure up an answer right now! Based on the knowledge sources provided, I can offer some insights on your multi-tenant setup using Prisma, Neon, and Next.js. You're correct that typically the Prisma Client is instantiated once with a single database URL. However, for multi-tenant scenarios like yours, where each user has their own database, a different approach is needed. One possible solution is to use a factory function to dynamically create Prisma Clients based on tenant-specific configurations. This approach is described in the Prisma documentation for dynamic usage with Next.js:
// lib/prismaDynamic.ts
import { PrismaClient } from "@prisma/client";

type TenantConfig = {
databaseUrl: string;
};

export function createPrismaClient(config: TenantConfig): PrismaClient {
return new PrismaClient({
datasources: {
db: {
url: config.databaseUrl,
},
},
});
}
// lib/prismaDynamic.ts
import { PrismaClient } from "@prisma/client";

type TenantConfig = {
databaseUrl: string;
};

export function createPrismaClient(config: TenantConfig): PrismaClient {
return new PrismaClient({
datasources: {
db: {
url: config.databaseUrl,
},
},
});
}
This approach allows you to create separate Prisma Clients for each tenant at runtime. However, it's crucial to manage the lifecycle of these dynamically created clients to avoid resource exhaustion. Your concern about creating new Prisma Client instances for each request is valid. Instead, you could consider maintaining a map or similar structure of Prisma Client instances in your Next.js app, one for each database/schema instance requested. This approach is discussed in a GitHub issue about multi-tenancy setups. However, this approach comes with its own challenges: 1. It can result in numerous Prisma Client instances based on the number of databases/schemas requested. 2. You'll need to implement a mechanism to purge unused clients after a certain amount of time. 3. There's a risk of memory issues if there are too many Prisma Client instances. It's worth noting that Prisma is aware o f the need for better multi-tenancy support. There's an ongoing feature request for isolating multi-tenant data via database schemas, which might provide a more elegant solution in the future.
Given the complexity of your multi-tenant setup and the unique requirements of your project, it might be helpful to reach out to the Prisma Team for more personalized guidance on implementing this architecture effectively.
✅ Great, thanks for letting us know that this solved your question!

Did you find this page helpful?