[object Object]

Custom Modules turn Freshsales from a CRM into a lightweight database. Subscriptions, properties, vehicles, contracts — anything you would otherwise track in a spreadsheet. Most teams over-model on day one and regret it.

Modeling rules of thumb

  • One module per noun your business cares about
  • Lookup fields, not duplicated data
  • Validate cardinality before you build (1:N vs N:N)
  • Use record types within a module, not five near-identical modules

Cardinality first

If a contact can own multiple subscriptions, that is 1:N (Subscription has lookup to Contact). If a subscription has multiple contacts (billing + technical), that is N:N. Freshsales N:N is implemented via a join module — plan it explicitly.

Subscription
  ├─ lookup: Account (1:N)
  └─ join: SubscriptionContact (N:N to Contact)
        ├─ lookup: Subscription
        └─ lookup: Contact
        └─ field: role (billing, technical, exec)

Field type pitfalls

  • Decimal field has fixed precision; choose 2 vs 4 at create time
  • Multi-select dropdown values cannot be deleted once data exists
  • Lookup fields cannot change target module; you have to recreate

Use record types for variants

A “Contract” module might have Master, Amendment, Renewal types. Do not build three modules. Use a record type field with a workflow that controls visible fields per type.

API patterns

Custom Module records use the same API surface as core modules:

POST /api/cpq/v1/modules/{module_name}/records
{
  "data": {
    "name": "ACME Annual 2026",
    "subscription_status": "active",
    "linked_account_id": 9921
  }
}

Reporting limits

Custom Modules show up in Analytics, but cross-module joins beyond two hops can hit query limits. Pre-aggregate if you need three-hop reports — store rolled-up values on the parent.

Permissions

Field-level permissions on Custom Modules require Enterprise tier. On Pro tier, plan around module-level access rather than field-level.

What to do this week

List the nouns you currently track outside Freshsales, draw the cardinality diagram before opening the admin panel, pick decimal precision deliberately, and use record types instead of cloning modules.

[object Object]
Share