Skip to content

Commit 4421512

Browse files
improvement(tables): make max row size env-configurable and raise default to 400KB (#5338)
1 parent eb367de commit 4421512

3 files changed

Lines changed: 18 additions & 4 deletions

File tree

apps/sim/lib/core/config/env.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ export const env = createEnv({
9494
TEAM_TABLE_ROWS_LIMIT: z.number().optional(), // Max rows per table on team tier (default: 500000)
9595
ENTERPRISE_TABLES_LIMIT: z.number().optional(), // Max user tables per workspace on enterprise tier (default: 10000)
9696
ENTERPRISE_TABLE_ROWS_LIMIT: z.number().optional(), // Max rows per table on enterprise tier (default: 1000000)
97+
TABLE_MAX_ROW_SIZE_BYTES: z.number().optional(), // Max serialized size in bytes of a single user-table row (default: 409600)
9798

9899
// Credit-tier Stripe prices (monthly)
99100
STRIPE_PRICE_TIER_25_MO: z.string().min(1).optional(), // Pro: $25/mo (6,000 credits)

apps/sim/lib/table/constants.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { env, envNumber } from '@/lib/core/config/env'
88
export const TABLE_LIMITS = {
99
MAX_TABLES_PER_WORKSPACE: 100,
1010
MAX_ROWS_PER_TABLE: 10000,
11-
MAX_ROW_SIZE_BYTES: 100 * 1024, // 100KB
11+
MAX_ROW_SIZE_BYTES: 400 * 1024, // 400KB
1212
MAX_COLUMNS_PER_TABLE: 50,
1313
MAX_TABLE_NAME_LENGTH: 128,
1414
MAX_COLUMN_NAME_LENGTH: 50,
@@ -61,6 +61,18 @@ export const DEFAULT_TABLE_PLAN_LIMITS = {
6161
},
6262
} as const
6363

64+
/**
65+
* Maximum serialized size in bytes of a single row. Defaults to
66+
* `TABLE_LIMITS.MAX_ROW_SIZE_BYTES`; overridable via the
67+
* `TABLE_MAX_ROW_SIZE_BYTES` env var (server-only, read at call time).
68+
*/
69+
export function getMaxRowSizeBytes(): number {
70+
return envNumber(env.TABLE_MAX_ROW_SIZE_BYTES, TABLE_LIMITS.MAX_ROW_SIZE_BYTES, {
71+
min: 1,
72+
integer: true,
73+
})
74+
}
75+
6476
export type PlanName = keyof typeof DEFAULT_TABLE_PLAN_LIMITS
6577

6678
export interface TablePlanLimits {

apps/sim/lib/table/validation.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { userTableRows } from '@sim/db/schema'
77
import { and, eq, or, type SQL, sql } from 'drizzle-orm'
88
import { NextResponse } from 'next/server'
99
import { getColumnId } from '@/lib/table/column-keys'
10-
import { COLUMN_TYPES, NAME_PATTERN, TABLE_LIMITS } from '@/lib/table/constants'
10+
import { COLUMN_TYPES, getMaxRowSizeBytes, NAME_PATTERN, TABLE_LIMITS } from '@/lib/table/constants'
1111
import { withSeqscanOff } from '@/lib/table/planner'
1212
import type {
1313
ColumnDefinition,
@@ -356,11 +356,12 @@ export function coerceRowToSchema(data: RowData, schema: TableSchema): Validatio
356356

357357
/** Validates row data size is within limits. */
358358
export function validateRowSize(data: RowData): ValidationResult {
359+
const maxRowSizeBytes = getMaxRowSizeBytes()
359360
const size = JSON.stringify(data).length
360-
if (size > TABLE_LIMITS.MAX_ROW_SIZE_BYTES) {
361+
if (size > maxRowSizeBytes) {
361362
return {
362363
valid: false,
363-
errors: [`Row size exceeds limit (${size} bytes > ${TABLE_LIMITS.MAX_ROW_SIZE_BYTES} bytes)`],
364+
errors: [`Row size exceeds limit (${size} bytes > ${maxRowSizeBytes} bytes)`],
364365
}
365366
}
366367
return { valid: true, errors: [] }

0 commit comments

Comments
 (0)