Forge64 logo
All app types

CRM scaling

CRM scaling and launch checklist

A CRM stays fast by paginating every list, indexing the main questions, and deferring heavy work until a measured trigger fires. At launch, apply 10 rules, watch 8 signals and hold the performance targets below.

Last checked

Rules to apply at launch

  • Pagination: Every table view, record timeline, kanban column and search uses keyset pagination over an indexed sort key plus id, page size capped at 100; the query builder refuses sorts and filters on non-indexed columns for large entities and never emits OFFSET.
  • Search: Filters are a validated AST compiled by one parameterised query builder (allow-listed fields and operators, fields the viewer cannot read are rejected), with statement_timeout (STATEMENT_TIMEOUT_MS) and a row cap on every request; free-text uses tsvector GIN and trigram GIN.
  • Search: Custom fields live in a jsonb column with a GIN jsonb_path_ops index for containment filters; range sorts on a custom field are allowed only after the field is promoted to a typed column by migration. EAV tables are rejected because filtering needs a join per field.
  • Idempotency: Jobs are chunked (500 rows) and idempotent: imports upsert on email_norm/domain, bulk ops record (bulk_op_id, chunk_no), exports are rebuilt not resumed, and API creates accept an Idempotency-Key header, so a retry or double click never duplicates or double-applies.
  • Idempotency: Records carry a version integer; updates send the expected version and a mismatch returns 409 with the current record, so two reps editing the same deal cannot silently overwrite each other.
  • Caching: Dashboards and reports read report_daily rollups and a per-workspace cached KPI payload (revalidated on write via tag) instead of aggregating deals or activities per request; the kanban fetches 50 cards per stage and hydrates owners with one batched query.
  • Rate limits: Per-user and per-workspace limits on search, record writes, imports, exports and bulk ops (for example 1 concurrent import, 3 exports per hour, 5 bulk ops per hour per user); over-limit requests get 429 with Retry-After and are never queued silently.
  • Data growth: audit_log and deal_stage_history are append-only and partitioned (monthly and yearly); activities partition by year past 50M rows; notifications and export/import metadata have retention deletes; reports never scan raw history.
  • Storage: Import sources and export files live in private buckets with lifecycle expiry (sources 7 days, exports 24 h); attachments on records are capped per file and per workspace.

Performance targets

Performance targets for a CRM
What to measureTarget
Table view page (100 rows, filtered, sorted)p95 < 300 ms, <= 5 queries, index-backed at 1M contacts
Record page (fields, timeline first 25, tasks)p95 < 250 ms; LCP < 2.5 s
Kanban board load (6 stages x 50 cards)p95 < 400 ms; card move p95 < 150 ms
Global searchp95 < 300 ms, <= 50 results, keyset paginated
Dashboard / report loadp95 < 500 ms from rollups, no raw table scans
Import throughput>= 1,000 rows per second validated, >= 500 rows per second committed per worker; 50k rows under 3 minutes
Export of 50k rowsready in < 60 s; no impact on interactive p95

What to watch

  • Metric query latency ms by view: histogram for list/search queries by entity and filter shape; slow-query log above 500 ms.
  • Metric import export volume: rows imported and exported per user per day; feeds the exfiltration alert.
  • Metric conflict 409 rate: optimistic concurrency conflicts per entity; a rise means a UX or race problem.
  • Log structured audit-adjacent request logs: request id, hashed actor id, entity, action, row count; no field values, no PII, no tokens.
  • Trace import upload -> validate -> commit trace: one trace id across the three stages with row counts.
  • Slo crm availability: 99.9% of record and list requests succeed under 1 s; error budget reviewed monthly.
  • Alert audit chain break: any hash-chain verification failure pages immediately.
  • Alert bulk or import stuck: job running > 15 min without chunk progress, or failure rate > 5% over 30 min.

Recurring work

  • validate_import: runs queue (import_jobs uploaded). Guard: streams the file, max IMPORT_MAX_MB and IMPORT_MAX_ROWS, writes at most 1,000 error rows, commits nothing, attempt cap 3.
  • commit_import: runs queue (user confirmed). Guard: chunks of 500 upserted on email_norm or domain, chunk results idempotent, stops and reports on the first systemic error, per-workspace concurrency of 1 import.
  • build_export: runs queue (export_jobs). Guard: keyset walk, row count checked against EXPORT_MAX_ROWS before writing, field permissions applied, formula-injection neutralised, file expires in EXPORT_URL_TTL_SECONDS.
  • apply_bulk_op: runs queue (bulk_ops). Guard: matched_rows <= BULK_MAX_ROWS, chunks of 500 keyed by (bulk_op_id, chunk_no), per-record permission re-check and audit entry, version check skips conflicted records and reports them.
  • rollup_report_daily: runs cron 15m. Guard: recomputes only days touched since last run, upsert by (day, owner, pipeline, stage), bounded batch.
  • task_reminders: runs cron 1m. Guard: claims due reminders with SKIP LOCKED, dedupes per (user, task), REMINDER_EMAILS_PER_USER_DAY cap.

Add when the numbers say so

  • Read replicas: Route report, search and export reads to a read replica when primary CPU or read latency crosses the trigger; the data layer separates read and write paths so this is configuration, and exports already tolerate replica lag.
  • Fanout: Outbound webhooks and automation are driven from a transactional outbox with per-endpoint queues, signed payloads, backoff and circuit breakers so one slow subscriber cannot stall others.
  • Search: Move global search to a dedicated search engine once tsvector/trigram latency or index size crosses the trigger; the query builder already isolates search behind one interface.

Deferred until it is needed

Work to defer for a CRM, with the trigger for adopting it
DeferredAdopt it when
Outbound webhooks and a public REST API with scoped keysfirst integration request or > 20% of customers ask.
Email and calendar sync (Gmail / Microsoft 365 OAuth)email logging is the top requested feature.
Workflow automation engine and duplicate-merge toolingcustomers hand-run the same steps > 20 times a week.
Dedicated search engine (OpenSearch/Typesense)> 10M records per workspace or search p95 > 300 ms.
Read replicas for reports, search and exportsprimary CPU > 60% sustained or report p95 > 500 ms.
Real-time co-editing and live presencefrequent simultaneous edits on the same record.

On Forge64

Forge64 matches your description to one of 12 reference architectures, writes the plan and data model into the project, generates the app, and runs a quality gate over the code before you see it. Each app gets its own Postgres database and sign-in with no per-user fee. Hosting on Forge Cloud and Forge Payments are rolling out.

Every metered resource on Forge64 has a hard cap, so a traffic spike stops at your limit instead of becoming a surprise bill. This is a reference design for the category, not a promise that every item is generated today. Built-ins such as email, background jobs, file uploads and search are coming soon, so anything here that needs them is something you add yourself for now.

FAQ

When should I worry about scale for a CRM?
Not before a measured trigger fires. For example, for "Outbound webhooks and a public REST API with scoped keys": first integration request or > 20% of customers ask.
What performance targets should a CRM aim for?
Table view page (100 rows, filtered, sorted): p95 < 300 ms, <= 5 queries, index-backed at 1M contacts. Record page (fields, timeline first 25, tasks): p95 < 250 ms; LCP < 2.5 s. Kanban board load (6 stages x 50 cards): p95 < 400 ms; card move p95 < 150 ms.
Does Forge64 cap my usage costs?
Yes. Every metered resource has a hard cap, and paid plans add an overage spend cap that you set.

Build your app with Forge64

One prompt to a running app with auth, database, hosting and payments. Start free, no credit card required.

Start building for free