superapp
AdvancedSecurity

Request Limits

Rate limiting and query constraints.

Chat in Claude

The engine enforces limits on query complexity, request size, and request frequency to prevent abuse and protect downstream databases.

const engine = createEngine({
  limits: {
    maxRows: 10_000,              // max rows a query can return
    maxRelationDepth: 3,          // orders → items → product = depth 3
    maxFilterNesting: 5,          // nested $and/$or/$not levels
    maxFilterConditions: 20,      // total conditions per query
    maxRequestBodySize: '1mb',    // max JSON body size
    queryTimeout: 30_000,         // kill slow queries (ms)
    rateLimitPerUser: 200,        // req/min per user
    rateLimitPerIP: 500,          // req/min per IP
  },
})

All Limits

LimitDefaultErrorDescription
maxRows10_000400 Limit exceeds maximum of 10000Cap on rows returned per query
maxRelationDepth3400 Relation depth exceeds maximum of 3How many levels deep relations can be nested
maxFilterNesting5400 Filter nesting exceeds maximum of 5How many levels deep $and/$or/$not can nest
maxFilterConditions20400 Filter has too many conditions (max 20)Total filter conditions per query
maxRequestBodySize'1mb'413 Request body too largeMaximum JSON body size
queryTimeout30_000408 Query timed out after 30000msMaximum query execution time in milliseconds
rateLimitPerUser200429 Rate limit exceeded, retry after {n}sRequests per minute per authenticated user
rateLimitPerIP500429 Rate limit exceeded, retry after {n}sRequests per minute per IP address

Query Complexity Limits

maxRows

Caps the limit parameter on findMany queries. If a client requests more rows than allowed, the engine returns an error instead of silently truncating:

// Client request
db.main.orders.findMany({ limit: 50_000 })
// → 400 Limit exceeds maximum of 10000

maxRelationDepth

Prevents deeply nested relation joins that could generate expensive multi-table queries:

// Depth 1: orders → customers
// Depth 2: orders → customers → organizations
// Depth 3: orders → customers → organizations → members (max)
db.main.orders.findMany({
  include: {
    customer: {
      include: {
        organization: {
          include: {
            members: true, // depth 3 — allowed
          },
        },
      },
    },
  },
})

maxFilterNesting

Limits how deeply $and and $or conditions can be nested inside each other:

// Nesting level 1
{ $or: [
  // Nesting level 2
  { $and: [
    { status: { $eq: 'active' } },
    { amount: { $gt: 100 } },
  ]},
  { status: { $eq: 'pending' } },
]}

maxFilterConditions

Caps the total number of filter conditions across all nesting levels. This prevents clients from constructing queries with hundreds of $or branches.

Request Size Limits

maxRequestBodySize

Rejects requests with JSON bodies larger than the configured size. Accepts string values like '1mb', '500kb', or '2mb'.

Timeout

queryTimeout

Kills queries that run longer than the specified duration. The database connection is released and the client receives a 408 error. This protects against unoptimized queries or unexpected table scans.

Rate Limiting

Rate limits use a sliding window counter. When a client exceeds the limit, subsequent requests receive a 429 response with a Retry-After header.

rateLimitPerUser

Tracks requests by the sub claim in the JWT. Authenticated users share no state with other users.

rateLimitPerIP

Tracks requests by client IP address. This catches unauthenticated abuse and limits the blast radius of a compromised user token.

Both limits are applied independently. A request must pass both checks.

Overriding Per-Environment

Use different limits for development and production:

const isProd = process.env.NODE_ENV === 'production'

const engine = createEngine({
  limits: {
    // Tighter limits in production, relaxed for local development
    maxRows:          isProd ? 10_000  : 100_000,
    rateLimitPerUser: isProd ? 200     : 10_000,
    rateLimitPerIP:   isProd ? 500     : 10_000,
    queryTimeout:     isProd ? 30_000  : 120_000,
  },
})

On this page