Prisma 7.8.0 requires a security-first approach to data access, configuration, and transaction lifecycle management. While it provides type-safe query building to mitigate standard SQL injection risks, it does not implicitly enforce multi-tenant data isolation or granular access control logic, which must be implemented at the application layer. Developers must configure datasource URLs and environment-based secrets explicitly, use transaction-specific clients for operations inside interactive transactions, and apply robust pagination and authorization checks.
Essential implementation rules
Enforce Tenant Isolation and Ownership at the Query Level
Scope each owner-restricted operation with a where clause containing the authenticated user’s ownership identifier, and enforce authentication and authorization in application logic. Use tenant-specific Prisma Client query extensions where appropriate, ensure application code uses the correctly scoped client, and use non-nullable ownership fields such as authorId when every record must have an owner.
Use Transaction-Specific Clients for Atomic Operations
Always use the tx instance provided within an interactive $transaction callback rather than the global prisma client. This ensures database operations execute atomically and within the intended scope to maintain data integrity and prevent partial updates.
Secure Database Connections via Driver Adapters
Instantiate PrismaClient with the required Driver Adapter and explicitly pass a validated, secret-managed connection URL. For adapters such as PrismaNeonHttp, provide the adapter’s database connection string through the designated environment variable.
Prevent SQL Injection in Raw Queries
Avoid concatenating dynamic input into raw SQL strings. Use Prisma’s tagged template literals for $queryRaw and $executeRaw to automatically parameterize inputs and prevent command injection.
Load Configuration Secrets Explicitly
Prisma 7.x does not auto-load .env files. Explicitly load environment variables, for example by importing dotenv/config, before accessing required database credentials from prisma.config.ts.
Manage Resource Consumption with Pagination
Mitigate resource exhaustion by implementing pagination with take and skip, or cursor-based pagination for large result sets. Limit nested include or select depth and breadth to prevent complex and expensive queries.
Ensure Cryptographic Integrity in Polyfilled Environments
When using globalThis.crypto compatibility helpers, always await asynchronous operations like digest(). Check that the corresponding crypto API, such as randomUUID or randomFillSync, is available before invoking it.
Enforce Transactional Consistency for Sensitive Logic
Use explicit isolation levels such as Serializable for complex, sensitive transactions. After applying schema mutations or migrations, always run prisma generate to update the Prisma Client and reconcile runtime type definitions with the database schema.
Do Not Infer Query-Argument Capture from the Tracing Example
Prisma’s tracing example demonstrates tracing setup, but it does not establish that query arguments are captured in spans or prescribe redacting them before a query. Do not cite that example as evidence for either behavior.
Enforce Strict Environment Configuration
Define migration paths and datasource URLs explicitly in prisma.config.ts, source connection strings from the intended environment rather than hardcoding credentials, and verify the selected environment before running migration commands.
prisma: All Security Cards
Approximately 5,057 tokens
On this card
Category: access control
Enforce Access Control with Ownership and Role Checks
Use when
When implementing data access logic in applications using Prisma, especially for operations that modify or retrieve sensitive information.
Secure rules
Rule 1: Verify that the authenticated actor has the necessary permissions (e.g., ownership, role) before allowing an action on a resource.
Before performing any database operation that could expose or modify sensitive data, ensure that the current user or tenant has the explicit permission to do so. This prevents unauthorized access and cross-tenant data leakage. For example, when updating a record, always check if the authenticated user is the owner of that record.
Rule 2: Use tenant-specific Prisma Client extensions when implementing multi-tenant data isolation.
Use Prisma Client’s query extension component to create an independent extended client customized for a specific user or tenant, such as by binding the client to the appropriate filter. Prisma documents this as a way to implement user isolation, including through a PostgreSQL row-level security (RLS) extension. Ensure application code uses the appropriately scoped client; Prisma does not automatically add tenant filters to every query.
Developing applications that manage multi-user or multi-tenant data, or require strict record-level access control.
Secure rules
Rule 1: Scope Prisma queries by the authenticated user’s ownership identifier.
Define ownership relationships in your Prisma schema and include the authenticated user’s identifier in the where clause of every operation that must be owner-scoped. The filter limits the records affected or returned by that operation, but it does not authenticate the user or automatically protect queries where the filter is omitted; validate the identity and enforce authorization in application logic. Make critical ownership identifiers such as authorId non-nullable when every record must have an owner, which maintains that data-integrity invariant but does not itself enforce access control.
model Post { id Int @id @default(autoincrement()) authorId Int // Required ownership reference title String content String}// To fetch posts for a specific user:const userId: number = authenticatedUser.id;const userPosts = await prisma.post.findMany({ where: { authorId: userId, },});
Rule 2: Isolate data models and access controls between different database environments or drivers using separate schema files.
When working with distinct database environments (e.g., different cloud providers or adapters) or requiring separate access boundaries, use dedicated schema.prisma files for each. Generate the Prisma Client specifically for each schema to enforce isolation and prevent accidental data exposure across environments.
Use Transactional Client Instances Within Interactive Transactions
Use when
Executing database operations within Prisma’s interactive transactions.
Secure rules
Rule 1: Always use the transaction-specific client instance (tx) provided within the interactive transaction callback, rather than the global Prisma client instance.
When using Prisma’s interactive transactions with the $transaction method that accepts an async callback, ensure all database operations inside the callback are performed using the tx argument. Using the global prisma client instance instead of tx will cause operations to execute outside the transaction, potentially leading to race conditions, partial updates, and data integrity issues.
Configure Prisma migrations with secure, environment-specific settings
Use when
Setting up Prisma migrations, managing database credentials, or configuring the migration environment.
Secure rules
Rule 1: Isolate database connection strings for different environments using environment variables.
Use a dedicated connection string for each database environment and provide it through an environment variable. Select the intended environment’s variable when running Prisma commands, and avoid hardcoding connection strings in prisma.config.ts.
# Configure this separately in each environment:DATABASE_URL="postgres://user:pass@host/db"# Then specify in prisma.config.ts:import { defineConfig, env } from 'prisma/config'export default defineConfig({ schema: 'prisma/schema.prisma', migrations: { path: 'prisma/migrations', }, datasource: { url: env('DATABASE_URL'), },})
Rule 2: Explicitly define migration configuration in prisma.config.ts.
Define the migrations path and datasource.url explicitly in your prisma.config.ts file so the migration directory and database connection source are clear and reviewable. Source the URL from an environment variable rather than hardcoding credentials, and verify the selected environment before running migration commands.
Rule 3: Manually load environment variables for migration tasks in Prisma 7.x.
Since Prisma 7.x no longer automatically loads .env files, you must manually implement this, for example, by using a dotenv package. This ensures that migration commands have access to the necessary database credentials and secrets, preventing failures or fallbacks to insecure defaults.
Rule 4: Use a branch-specific PlanetScale password for schema operations.
When configuring PlanetScale for Prisma’s driver-adapter workflow, create a new password for the intended database branch (e.g., ‘main’), select the Prisma template, and store the generated connection URL in JS_PLANETSCALE_DATABASE_URL. Use that branch-specific connection URL when running the PlanetScale schema-push workflow.
JS_PLANETSCALE_DATABASE_URL="mysql://USER:PASSWORD@HOST/DATABASE?sslaccept=strict"# Use the credentials generated for the intended branch with the Prisma template.
Rule 5: Re-generate the Prisma Client after schema changes to maintain runtime consistency.
After applying any schema changes or migrations, regularly re-generate the Prisma Client. This ensures that your application’s runtime queries align with the current database state, preventing potential bypasses of new schema-level security constraints or runtime errors due to structural mismatches.
Configuring database connections and driver adapters in Prisma version 7.8.0.
Secure rules
Rule 1: Define the datasource connection URL in prisma.config.ts.
Prisma 7.x supports defining the datasource connection URL in prisma.config.ts. Set datasource.url to a static value or load a required value from an environment variable with the env helper.
Rule 2: Provide validated connection strings to mandatory driver adapters.
Prisma 7.8.0 mandates the use of Driver Adapters for all database connections. When initializing an adapter, such as PrismaPlanetScale, explicitly pass the connection URL as an object property. Ensure this connection string is validated and sourced from a secure environment provider.
const adapter = new PrismaPlanetScale({ url: process.env.JS_PLANETSCALE_DATABASE_URL})
Implement cryptographic operations using secure and available primitives
Use when
Using cryptographic functions like hashing or random number generation within your application, especially when leveraging Prisma’s compatibility layers.
Secure rules
Rule 1: Always await asynchronous cryptographic hash digests when using polyfilled modules.
When Prisma polyfills Node.js crypto functions using the Web Crypto API, such as with globalThis.crypto.subtle.digest, ensure you always await the digest() method. This prevents race conditions and ensures data integrity by completing the hash calculation before proceeding.
import { createHash } from 'crypto';async function hashData(data: string): Promise<ArrayBuffer> { const hash = createHash('SHA-256'); hash.update(new TextEncoder().encode(data)); const result = await hash.digest(); return result;}
Rule 2: Ensure the runtime environment provides the cryptographic APIs used by Prisma.
Prisma’s crypto compatibility code relies on globalThis.crypto for helpers such as randomUUID and randomFillSync. Some Prisma call sites check whether a helper is available before invoking it. Guard calls in the same way: invoke these helpers only when the corresponding crypto API is available, because an unavailable API can cause a runtime failure.
When executing raw SQL queries or commands directly against the database.
Secure rules
Rule 1: Use parameterized raw SQL queries instead of unsafe, unparameterized execution, especially with external input.
Prisma provides safe methods for executing raw SQL. Always use parameterized queries when including dynamic data, and avoid methods that execute unparameterized SQL strings, as they are susceptible to SQL injection. Leverage Prisma Client’s type-safe methods for most operations.
await prisma.$queryRaw`SELECT * FROM User WHERE id = ${userId}`
When interacting with the database using Prisma Client, especially when constructing queries with user-provided data.
Secure rules
Rule 1: Always use parameterized queries or the Prisma Client API to prevent SQL injection when handling untrusted input.
When performing database operations with user-supplied input, ensure that the input is always passed through Prisma’s built-in parameterization mechanisms. This includes using the standard Prisma Client methods as shown in the example, or explicitly using tagged template literals with $queryRaw and $executeRaw for raw SQL, rather than concatenating strings. This prevents untrusted data from being interpreted as SQL commands.
await prisma.user.create({ data: { email: userInputEmail, },});const userId = 123;const result = await prisma.$queryRaw`SELECT * FROM User WHERE id = ${userId}`;
Ensure Accurate Type Matching for Query Parameters
Use when
When manually constructing query plans or extensions in Prisma Client, especially when dealing with specialized data types.
Secure rules
Rule 1: Validate that parameter types used in query plans precisely match their expected runtime types to prevent data corruption or misinterpretation.
When building custom query logic or extensions, always confirm that the types of parameters, particularly for specialized types like DateTime, Decimal, BigInt, and JSON/JSONB, align with what the database driver and Prisma expect. Use Prisma’s built-in type constructors to ensure correct serialization.
import { Prisma } from '@prisma/client';const decimalValue = new Prisma.Decimal('10.5');const bigIntValue = BigInt('9007199254740991');// Example usage within a Prisma client operation (conceptual)// await prisma.myModel.findMany({// where: {// decimalField: decimalValue,// bigIntField: bigIntValue// }// });
Instantiate Prisma Client with a Mandatory Driver Adapter
Use when
Initializing PrismaClient in Prisma version 7.8.0.
Secure rules
Rule 1: Always provide a mandatory driver adapter when instantiating PrismaClient.
In Prisma version 7.8.0 and later, the Prisma Client requires a driver adapter to manage database communication. Ensure you explicitly instantiate the PrismaClient with a compatible driver adapter to establish a secure and functioning connection to your database.
import { PrismaBetterSqlite3 } from '@prisma/adapter-better-sqlite3'import { PrismaClient } from './generated/prisma/client'const adapter = new PrismaBetterSqlite3({ url: 'file:prisma/dev.db' })const prisma = new PrismaClient({ adapter })// For D1 specific adapter:// import { PrismaD1 } from '@prisma/adapter-d1'// const adapter = new PrismaD1(env.MY_DATABASE);// const prisma = new PrismaClient({ adapter });
Restrict database connections to authorized endpoints
Use when
Configuring Prisma Client to connect to a database, especially when using HTTP-based adapters or custom network configurations.
Secure rules
Rule 1: Configure the Neon HTTP adapter with its database connection string.
When using PrismaNeonHttp, store the Neon database connection string in the JS_NEON_DATABASE_URL environment variable and pass it to the adapter constructor.
const connectionString = `${process.env.JS_NEON_DATABASE_URL as string}`;const adapter = new PrismaNeonHttp(connectionString, { arrayMode: false, fullResults: true,});
Limit data fetching to prevent resource exhaustion
Use when
When querying data with Prisma, especially for large datasets or complex relationships.
Secure rules
Rule 1: Apply pagination and limit nested data retrieval to prevent excessive resource consumption.
When fetching data, use pagination with take and skip (or cursor for large datasets) to limit the number of records returned. Additionally, limit the depth and breadth of nested includes or selects to control query complexity and prevent memory or execution time exhaustion. For very large datasets, prefer cursor-based pagination over offset-based pagination (using skip) as it scales better.
Rule 2: Explicitly disconnect PrismaClient when no longer needed to avoid connection leaks.
In applications that manage PrismaClient instances for specific tasks or have a defined lifecycle, ensure that prisma.$disconnect() is called. Failing to do so can lead to connection leaks, exhausting database connection slots and causing a Denial of Service (DoS).
When developing or deploying applications using Prisma, especially in production environments.
Secure rules
Rule 1: Avoid relying on Node.js core modules (‘http’, ‘https’, ‘tls’, ‘net’, ‘dns’, ‘child_process’) in code bundled with Prisma’s fill-plugin configuration, where those modules are intentionally shimmed.
Prisma, in version 7.8.0, uses a fill-plugin during bundling that replaces these core Node.js modules with empty contents. Code built with this configuration should not require functionality from the shimmed modules. For Prisma database communication, use the supported database Driver Adapters.
Manage secrets using environment variables in Prisma
Use when
Configuring database connections or other sensitive settings in Prisma, especially after version 7.0.0.
Secure rules
Rule 1: Load environment variables for Prisma configuration and database connections.
In Prisma versions 7.x and later, environment variables are not automatically loaded. You must explicitly import and call a library like ‘dotenv/config’ at the beginning of your Prisma configuration file (e.g., prisma.config.ts) to ensure that all necessary secrets, such as DATABASE_URL, are available before they are used. Alternatively, use the env() helper function from @prisma/config to access environment variables, ensuring that sensitive values like database connection strings are never hardcoded directly in your Prisma schema or configuration files to prevent leakage.
Rule 2: Prisma’s tracing example does not establish query-argument capture.
Prisma’s tracing example demonstrates tracing setup, but it does not establish that Prisma query arguments are captured in spans or prescribe redacting those arguments before a query. Do not treat the example as evidence for either behavior.
Ensure Transactional Integrity with Explicit Isolation Levels
Use when
When performing sensitive database operations that require strict data consistency and atomicity, especially within transactions.
Secure rules
Rule 1: Enforce strict isolation levels for sensitive transactional operations to prevent race conditions and data corruption.
When executing a series of dependent database operations that must be isolated from concurrent modifications, explicitly configure the ‘Serializable’ isolation level for transactions. This prevents phenomena like non-repeatable reads or phantom reads, ensuring data consistency for security-sensitive logic.
Rule 2: Execute dependent database operations within atomic interactive transactions to guarantee data consistency and atomicity.
To prevent inconsistent database states that could lead to business logic bypasses or data corruption, wrap related operations within a $transaction block. Use an async callback within $transaction to ensure that if any part of a complex operation fails, the entire set of changes is rolled back atomically.
Enforce Access Control with Ownership and Role Checks
Approximately 747 tokens
Use when
When implementing data access logic in applications using Prisma, especially for operations that modify or retrieve sensitive information.
Secure rules
Rule 1: Verify that the authenticated actor has the necessary permissions (e.g., ownership, role) before allowing an action on a resource.
Before performing any database operation that could expose or modify sensitive data, ensure that the current user or tenant has the explicit permission to do so. This prevents unauthorized access and cross-tenant data leakage. For example, when updating a record, always check if the authenticated user is the owner of that record.
Rule 2: Use tenant-specific Prisma Client extensions when implementing multi-tenant data isolation.
Use Prisma Client’s query extension component to create an independent extended client customized for a specific user or tenant, such as by binding the client to the appropriate filter. Prisma documents this as a way to implement user isolation, including through a PostgreSQL row-level security (RLS) extension. Ensure application code uses the appropriately scoped client; Prisma does not automatically add tenant filters to every query.
Developing applications that manage multi-user or multi-tenant data, or require strict record-level access control.
Secure rules
Rule 1: Scope Prisma queries by the authenticated user’s ownership identifier.
Define ownership relationships in your Prisma schema and include the authenticated user’s identifier in the where clause of every operation that must be owner-scoped. The filter limits the records affected or returned by that operation, but it does not authenticate the user or automatically protect queries where the filter is omitted; validate the identity and enforce authorization in application logic. Make critical ownership identifiers such as authorId non-nullable when every record must have an owner, which maintains that data-integrity invariant but does not itself enforce access control.
model Post { id Int @id @default(autoincrement()) authorId Int // Required ownership reference title String content String}// To fetch posts for a specific user:const userId: number = authenticatedUser.id;const userPosts = await prisma.post.findMany({ where: { authorId: userId, },});
Rule 2: Isolate data models and access controls between different database environments or drivers using separate schema files.
When working with distinct database environments (e.g., different cloud providers or adapters) or requiring separate access boundaries, use dedicated schema.prisma files for each. Generate the Prisma Client specifically for each schema to enforce isolation and prevent accidental data exposure across environments.
Use Transactional Client Instances Within Interactive Transactions
Approximately 243 tokens
Use when
Executing database operations within Prisma’s interactive transactions.
Secure rules
Rule 1: Always use the transaction-specific client instance (tx) provided within the interactive transaction callback, rather than the global Prisma client instance.
When using Prisma’s interactive transactions with the $transaction method that accepts an async callback, ensure all database operations inside the callback are performed using the tx argument. Using the global prisma client instance instead of tx will cause operations to execute outside the transaction, potentially leading to race conditions, partial updates, and data integrity issues.
Configure Prisma migrations with secure, environment-specific settings
Approximately 1,121 tokens
Use when
Setting up Prisma migrations, managing database credentials, or configuring the migration environment.
Secure rules
Rule 1: Isolate database connection strings for different environments using environment variables.
Use a dedicated connection string for each database environment and provide it through an environment variable. Select the intended environment’s variable when running Prisma commands, and avoid hardcoding connection strings in prisma.config.ts.
# Configure this separately in each environment:DATABASE_URL="postgres://user:pass@host/db"# Then specify in prisma.config.ts:import { defineConfig, env } from 'prisma/config'export default defineConfig({ schema: 'prisma/schema.prisma', migrations: { path: 'prisma/migrations', }, datasource: { url: env('DATABASE_URL'), },})
Rule 2: Explicitly define migration configuration in prisma.config.ts.
Define the migrations path and datasource.url explicitly in your prisma.config.ts file so the migration directory and database connection source are clear and reviewable. Source the URL from an environment variable rather than hardcoding credentials, and verify the selected environment before running migration commands.
Rule 3: Manually load environment variables for migration tasks in Prisma 7.x.
Since Prisma 7.x no longer automatically loads .env files, you must manually implement this, for example, by using a dotenv package. This ensures that migration commands have access to the necessary database credentials and secrets, preventing failures or fallbacks to insecure defaults.
Rule 4: Use a branch-specific PlanetScale password for schema operations.
When configuring PlanetScale for Prisma’s driver-adapter workflow, create a new password for the intended database branch (e.g., ‘main’), select the Prisma template, and store the generated connection URL in JS_PLANETSCALE_DATABASE_URL. Use that branch-specific connection URL when running the PlanetScale schema-push workflow.
JS_PLANETSCALE_DATABASE_URL="mysql://USER:PASSWORD@HOST/DATABASE?sslaccept=strict"# Use the credentials generated for the intended branch with the Prisma template.
Rule 5: Re-generate the Prisma Client after schema changes to maintain runtime consistency.
After applying any schema changes or migrations, regularly re-generate the Prisma Client. This ensures that your application’s runtime queries align with the current database state, preventing potential bypasses of new schema-level security constraints or runtime errors due to structural mismatches.
Configuring database connections and driver adapters in Prisma version 7.8.0.
Secure rules
Rule 1: Define the datasource connection URL in prisma.config.ts.
Prisma 7.x supports defining the datasource connection URL in prisma.config.ts. Set datasource.url to a static value or load a required value from an environment variable with the env helper.
Rule 2: Provide validated connection strings to mandatory driver adapters.
Prisma 7.8.0 mandates the use of Driver Adapters for all database connections. When initializing an adapter, such as PrismaPlanetScale, explicitly pass the connection URL as an object property. Ensure this connection string is validated and sourced from a secure environment provider.
const adapter = new PrismaPlanetScale({ url: process.env.JS_PLANETSCALE_DATABASE_URL})
Implement cryptographic operations using secure and available primitives
Approximately 342 tokens
Use when
Using cryptographic functions like hashing or random number generation within your application, especially when leveraging Prisma’s compatibility layers.
Secure rules
Rule 1: Always await asynchronous cryptographic hash digests when using polyfilled modules.
When Prisma polyfills Node.js crypto functions using the Web Crypto API, such as with globalThis.crypto.subtle.digest, ensure you always await the digest() method. This prevents race conditions and ensures data integrity by completing the hash calculation before proceeding.
import { createHash } from 'crypto';async function hashData(data: string): Promise<ArrayBuffer> { const hash = createHash('SHA-256'); hash.update(new TextEncoder().encode(data)); const result = await hash.digest(); return result;}
Rule 2: Ensure the runtime environment provides the cryptographic APIs used by Prisma.
Prisma’s crypto compatibility code relies on globalThis.crypto for helpers such as randomUUID and randomFillSync. Some Prisma call sites check whether a helper is available before invoking it. Guard calls in the same way: invoke these helpers only when the corresponding crypto API is available, because an unavailable API can cause a runtime failure.
When executing raw SQL queries or commands directly against the database.
Secure rules
Rule 1: Use parameterized raw SQL queries instead of unsafe, unparameterized execution, especially with external input.
Prisma provides safe methods for executing raw SQL. Always use parameterized queries when including dynamic data, and avoid methods that execute unparameterized SQL strings, as they are susceptible to SQL injection. Leverage Prisma Client’s type-safe methods for most operations.
await prisma.$queryRaw`SELECT * FROM User WHERE id = ${userId}`
When interacting with the database using Prisma Client, especially when constructing queries with user-provided data.
Secure rules
Rule 1: Always use parameterized queries or the Prisma Client API to prevent SQL injection when handling untrusted input.
When performing database operations with user-supplied input, ensure that the input is always passed through Prisma’s built-in parameterization mechanisms. This includes using the standard Prisma Client methods as shown in the example, or explicitly using tagged template literals with $queryRaw and $executeRaw for raw SQL, rather than concatenating strings. This prevents untrusted data from being interpreted as SQL commands.
await prisma.user.create({ data: { email: userInputEmail, },});const userId = 123;const result = await prisma.$queryRaw`SELECT * FROM User WHERE id = ${userId}`;
Ensure Accurate Type Matching for Query Parameters
Approximately 297 tokens
Use when
When manually constructing query plans or extensions in Prisma Client, especially when dealing with specialized data types.
Secure rules
Rule 1: Validate that parameter types used in query plans precisely match their expected runtime types to prevent data corruption or misinterpretation.
When building custom query logic or extensions, always confirm that the types of parameters, particularly for specialized types like DateTime, Decimal, BigInt, and JSON/JSONB, align with what the database driver and Prisma expect. Use Prisma’s built-in type constructors to ensure correct serialization.
import { Prisma } from '@prisma/client';const decimalValue = new Prisma.Decimal('10.5');const bigIntValue = BigInt('9007199254740991');// Example usage within a Prisma client operation (conceptual)// await prisma.myModel.findMany({// where: {// decimalField: decimalValue,// bigIntField: bigIntValue// }// });
Instantiate Prisma Client with a Mandatory Driver Adapter
Approximately 316 tokens
Use when
Initializing PrismaClient in Prisma version 7.8.0.
Secure rules
Rule 1: Always provide a mandatory driver adapter when instantiating PrismaClient.
In Prisma version 7.8.0 and later, the Prisma Client requires a driver adapter to manage database communication. Ensure you explicitly instantiate the PrismaClient with a compatible driver adapter to establish a secure and functioning connection to your database.
import { PrismaBetterSqlite3 } from '@prisma/adapter-better-sqlite3'import { PrismaClient } from './generated/prisma/client'const adapter = new PrismaBetterSqlite3({ url: 'file:prisma/dev.db' })const prisma = new PrismaClient({ adapter })// For D1 specific adapter:// import { PrismaD1 } from '@prisma/adapter-d1'// const adapter = new PrismaD1(env.MY_DATABASE);// const prisma = new PrismaClient({ adapter });
Restrict database connections to authorized endpoints
Approximately 246 tokens
Use when
Configuring Prisma Client to connect to a database, especially when using HTTP-based adapters or custom network configurations.
Secure rules
Rule 1: Configure the Neon HTTP adapter with its database connection string.
When using PrismaNeonHttp, store the Neon database connection string in the JS_NEON_DATABASE_URL environment variable and pass it to the adapter constructor.
const connectionString = `${process.env.JS_NEON_DATABASE_URL as string}`;const adapter = new PrismaNeonHttp(connectionString, { arrayMode: false, fullResults: true,});
Limit data fetching to prevent resource exhaustion
Approximately 476 tokens
Use when
When querying data with Prisma, especially for large datasets or complex relationships.
Secure rules
Rule 1: Apply pagination and limit nested data retrieval to prevent excessive resource consumption.
When fetching data, use pagination with take and skip (or cursor for large datasets) to limit the number of records returned. Additionally, limit the depth and breadth of nested includes or selects to control query complexity and prevent memory or execution time exhaustion. For very large datasets, prefer cursor-based pagination over offset-based pagination (using skip) as it scales better.
Rule 2: Explicitly disconnect PrismaClient when no longer needed to avoid connection leaks.
In applications that manage PrismaClient instances for specific tasks or have a defined lifecycle, ensure that prisma.$disconnect() is called. Failing to do so can lead to connection leaks, exhausting database connection slots and causing a Denial of Service (DoS).
When developing or deploying applications using Prisma, especially in production environments.
Secure rules
Rule 1: Avoid relying on Node.js core modules (‘http’, ‘https’, ‘tls’, ‘net’, ‘dns’, ‘child_process’) in code bundled with Prisma’s fill-plugin configuration, where those modules are intentionally shimmed.
Prisma, in version 7.8.0, uses a fill-plugin during bundling that replaces these core Node.js modules with empty contents. Code built with this configuration should not require functionality from the shimmed modules. For Prisma database communication, use the supported database Driver Adapters.
Manage secrets using environment variables in Prisma
Approximately 481 tokens
Use when
Configuring database connections or other sensitive settings in Prisma, especially after version 7.0.0.
Secure rules
Rule 1: Load environment variables for Prisma configuration and database connections.
In Prisma versions 7.x and later, environment variables are not automatically loaded. You must explicitly import and call a library like ‘dotenv/config’ at the beginning of your Prisma configuration file (e.g., prisma.config.ts) to ensure that all necessary secrets, such as DATABASE_URL, are available before they are used. Alternatively, use the env() helper function from @prisma/config to access environment variables, ensuring that sensitive values like database connection strings are never hardcoded directly in your Prisma schema or configuration files to prevent leakage.
Rule 2: Prisma’s tracing example does not establish query-argument capture.
Prisma’s tracing example demonstrates tracing setup, but it does not establish that Prisma query arguments are captured in spans or prescribe redacting those arguments before a query. Do not treat the example as evidence for either behavior.
Ensure Transactional Integrity with Explicit Isolation Levels
Approximately 337 tokens
Use when
When performing sensitive database operations that require strict data consistency and atomicity, especially within transactions.
Secure rules
Rule 1: Enforce strict isolation levels for sensitive transactional operations to prevent race conditions and data corruption.
When executing a series of dependent database operations that must be isolated from concurrent modifications, explicitly configure the ‘Serializable’ isolation level for transactions. This prevents phenomena like non-repeatable reads or phantom reads, ensuring data consistency for security-sensitive logic.
Rule 2: Execute dependent database operations within atomic interactive transactions to guarantee data consistency and atomicity.
To prevent inconsistent database states that could lead to business logic bypasses or data corruption, wrap related operations within a $transaction block. Use an async callback within $transaction to ensure that if any part of a complex operation fails, the entire set of changes is rolled back atomically.