Most teams never make these decisions explicitly. They inherit a default pipeline, add fields under pressure, and three years later have a system that everybody distrusts and nobody can change.
In short
- A CRM is a model of how your business makes money, not a contact list with automation bolted on.
- The five decisions: objects, stages, fields, ownership, contracts.
- A stage is only real if a stranger with the definition sorts records the same way your rep does.
- Every field needs an owner, a source of truth and a reason to exist, or it becomes noise the team learns to ignore.
- Two systems writing the same field with no contract is the most common cause of "our data is a mess."
- Fix architecture before you automate. Automating an unclear model just produces confusion faster.
Decision 1: Objects — what exists
Objects are the nouns of your business. Modern CRMs converged on a similar core. HubSpot organizes contacts and companies as foundational objects (deduplicated by email and domain), with sales objects such as deals and leads, service objects such as tickets, and commerce objects such as products, quotes, invoices and subscriptions; associations between records are always two-way and can carry labels (HubSpot). Underneath, each object type has an identifier used by the API — contacts are 0-1, companies are 0-2, and custom objects take the form 2-XXX (HubSpot developers).
Salesforce-style models add the lead-to-opportunity conversion step, which Dynamics 365 Sales implements too: qualifying a lead creates the associated account, contact and opportunity records, with duplicate detection offered when a similar record already exists, and the lead itself moves to a closed view rather than disappearing (Microsoft Learn).
You do not need to love that model, but you must choose one consciously and apply it consistently, because reporting depends on where each record lives before and after qualification.
The custom object test
Before creating a custom object, ask three questions. If you answer yes to all three, it is an object. Otherwise it is a property.
- Does it have its own lifecycle (states it moves through over time)?
- Can there be more than one of it per related record?
- Does someone own it and maintain it independently?
A branch has a lifecycle (planned, live, paused), many contacts point to it, and an operations lead owns it. That's an object. "Preferred contact time" fails all three. That's a property.
Decision 2: Stages — what progress means
Stages are where CRM architecture usually breaks, because a stage looks like a label and behaves like a contract. Everything from conversion rates to forecast weighting reads from stages. HubSpot's pipeline settings even require explicit won and lost stages so that sales reports and analytics process deals correctly (HubSpot).
MitHub's rule: a stage is defined by what the buyer has done, not by what your team has done. "Proposal sent" is an internal activity — you can send a hundred proposals into silence. "Proposal reviewed with the decision maker" is a buyer state.
The stage definition test
For every stage, write five lines. If you cannot, the stage is a feeling.
| Element | Example for "Qualified" |
|---|---|
| Entry criteria | Spoke with a decision maker; need and timeframe confirmed; inside service area |
| Exit criteria | Application submitted, or disqualified with a reason |
| Observable evidence | A logged call over 2 minutes with qualification notes completed |
| Who moves it | The rep who spoke to them |
| Expected time in stage | 3 days |
Then run the real test: give the written definitions and five anonymized records to somebody outside the team. If their sorting does not match the rep's, your pipeline data is fiction and your forecast inherits it.
Decision 3: Fields — what you promise to know
Every field is a maintenance commitment. MitHub asks three questions before any field is created:
- What decision changes depending on this value?
- Who keeps it true, and how do they know when it is wrong?
- What should happen when it is empty — block, default, or flag?
Fields that fail question 1 are the reason reps hate the CRM. Fields that fail question 2 quietly go stale. Fields that fail question 3 break automations at 2 a.m.
Two more practical rules:
- Picklists over free text for anything you will ever group by. Free text cannot be reported on and cannot be validated.
- Machine fields separate from human fields. Enrichment writes to
enriched_*; humans write to human fields. When they disagree, you can see it instead of silently overwriting.
Decision 4: Ownership — who is responsible now
Ownership answers "who is on the hook?" and it needs to be unambiguous at every moment of a record's life. In practice that means:
- One owner field that is always populated, with a named fallback queue as the default.
- An owner history so you can reconstruct who had it when.
- A rule for transfer (what triggers it, who is notified, what happens to open tasks).
- A rule for inactivity (no activity in N days returns the record to a queue).
Ownership and routing are the same conversation viewed from two angles: routing assigns it, architecture guarantees it can never be null.
Decision 5: Data contracts — who may write what
This is the decision that almost nobody writes down, and it is the one that saves you. A data contract card is one small table per important field:
| Element | Example |
|---|---|
| Field | phone_primary (Contact) |
| Business meaning | The number we call first |
| Source of truth | Enrichment provider, overridden by a verified human correction |
| Systems allowed to write | Enrichment workflow, rep (manual), call system (verified flag only) |
| Format | E.164, e.g. +17065550147 |
| Validation | Rejected if not E.164; flagged if the call system reports invalid |
| Consumers | Routing, AI voice campaign, SMS compliance checks |
| If wrong | Calls fail silently; the lead looks contacted but never was |
The last row is the one that focuses the mind. Write it for your ten most important fields and you will find at least one where two systems both believe they are the source of truth.
A worked example
The following is a hypothetical design, written to show the shape of the output, not a MitHub client.
Imagine a consumer lender with twelve branches. Leads come from web forms, walk-ins, and reactivation of past borrowers.
Objects
| Object | Why it exists | Key associations |
|---|---|---|
| Contact | The borrower | Branch, Application, Calls |
| Branch (custom) | Location with its own hours, phone number, manager and status | Contacts, Applications |
| Application (deal) | One funding request with its own lifecycle | Contact, Branch |
| Call (activity) | Every human or AI call attempt and outcome | Contact, Application |
| Campaign | The source that produced the lead | Contact |
Note what is not here: no Company object, because consumer borrowers are individuals. Copying a B2B model into a B2C business creates a lot of empty records.
Application pipeline
| Stage | Entry criteria | Typical duration |
|---|---|---|
| New | Record created with phone and branch assigned | minutes |
| Contacted | A conversation happened, logged | 1 day |
| Qualified | Need, amount and eligibility confirmed | 2 days |
| In underwriting | Documents received | 3 days |
| Funded (won) | Money disbursed | — |
| Closed lost | Reason captured from a fixed list | — |
Two contracts that matter most here: branch_id (written only by the routing table, never by hand, because attribution and branch reporting both depend on it) and last_call_outcome (written only by the call platform, from a fixed list, because it drives follow-up).
Anti-patterns to hunt for
- The overloaded status field. One field storing pipeline state, payment state and call outcome. Split it.
- Field sprawl. Forty custom fields, six populated. Archive the rest; the noise costs more than the fields ever earned.
- Stages named after your team's actions. Rename them after the buyer's state.
- Silent overwrites. Two systems writing one field with no contract, last write wins, nobody logs it.
- Deleting instead of closing. Deleted records destroy history; Dynamics, for example, keeps disqualified leads as an audit trail you can reactivate (Microsoft Learn).
- No lost reason. Without it you cannot diagnose anything, and a diagnosis is the whole point of the diagnose chapter.
- Automating first. If you cannot draw the process, do not build it. See process mapping before automation.
A 90-minute architecture review
Run this on any CRM you inherit:
- List the objects actually in use and how they associate. Draw it on one page.
- Print the stages and ask three people to define each one from memory. Note every disagreement.
- Sort fields by fill rate. Anything under 20% is either dead or a broken promise.
- Find every field written by more than one system. Those are your missing contracts.
- Query records with no owner and records not touched in 30 days.
- Pick one real closed-won deal and reconstruct its history from the CRM alone. Whatever you cannot reconstruct is a gap in the architecture.
Step 6 is the honest one. If the system cannot tell you the story of a sale that already happened, it will not help you produce the next one.
Architecture is unglamorous work, and it is the foundation everything else stands on. In the Faculty of Revenue Reverse Engineering it sits between following the money and building, for a simple reason: the map you draw from real payments is the specification your CRM should implement.
