Case Study · CRM / SaaS · Data Architecture

CRM Custom Fields — metadata-driven dynamic schema, without losing search speed.

A CRM platform whose customers each wanted their own custom fields per entity, with fast filtering and search across them, without exploding the relational schema. A hybrid storage + metadata-driven architecture solved it.

Per-customer
Field definitions, field types,
validation rules, entity mapping
Hybrid storage
Structured fields → relational
Dynamic fields → JSON / KV
Fast filter
Selective indexing + optional
search engine for scale

The situation (why they called)

The CRM needed to let every customer define their own fields on the core entities (Contacts, Accounts, Deals, Tickets) — different field names, different types, different validation rules. And those custom fields had to be searchable and filterable just like the built-in ones — "show me all Deals where Custom Region = 'EMEA' and Custom Tier >= 3".

The team had two prototypes to choose between, both bad:

Neither could carry the customer base they were targeting.

The diagnosis

Three observations changed the design:

  1. Most custom fields are read-heavy and filter-heavy (sales reps slice and dice their pipeline), but write-rare. Optimise for read.
  2. A small fraction of custom fields drive most of the queries. Those need real database indexes; the long tail can stay flexible.
  3. The metadata about fields is small (hundreds of definitions per customer at most), but the data itself is large (millions of rows of values). Treat them differently.

The decision

Decision Metadata-driven architecture with hybrid storage. Field definitions live in a structured metadata layer the application reads at startup and refreshes on change. Field values live in a JSON column on the parent entity (PostgreSQL JSONB / SQL Server JSON) — fast colocated reads, no joins. The hot custom fields get explicit indexes generated from the metadata. The truly large customers add an optional search-engine layer (Elasticsearch / OpenSearch) for cross-field analytical queries.

The architecture, in four layers

1. Field-definition layer (metadata)

2. Value-storage layer (hybrid)

3. Search optimisation

4. UI & API layer

Key decisions (and what we said no to)

The outcome

Numbers Customers can define their own fields without engineering tickets — fully customisable CRM.
No schema explosion in the relational DB; entity tables stay clean.
Performance held through customer growth — hot fields are indexed automatically based on metadata; cold fields don't pay for indexes they don't use.
New business requirements onboard in days, not weeks — the same metadata layer that drives fields drives forms, APIs, and search.

What I'd do differently

I'd ship the search-engine layer earlier, even for small customers. We initially gated it behind "you've crossed N records" — which made sense for cost reasons, but also meant that any customer who hit a complex cross-field query in the relational DB had a noticeably worse experience until they crossed the threshold. The failure mode mattered more than the cost — a small monthly fee per customer would have been worth the consistent UX.


Have a CRM, ERP, or vertical SaaS where customers want to extend the schema themselves?