The data model decisions you cannot cheaply undo
Most of an org is reversible. A handful of early modelling choices are not, and they get made in the first fortnight by whoever is fastest to a whiteboard.
Platform & ArchitectureSalesforce is unusually forgiving. Fields can be added, layouts rearranged, automation rewritten, and most of it can happen on a Tuesday afternoon without anyone noticing.
That forgiveness makes the exceptions dangerous, because teams carry the "we can change it later" assumption into the small number of decisions where later means a migration, a rebuild, or a new org.
Here are the ones worth slowing down for.
1. Person Accounts
Enabling Person Accounts is effectively permanent. It is not a checkbox you untick, and it changes the shape of the Account object for every downstream consumer, reports, integrations, packages, automation.
The question is not "do we sell to consumers". It is whether an individual is ever a customer in their own right, with no organisation above them.
- Retail, wealth, healthcare, education, member organisations, usually yes.
- Pure B2B where every contact belongs to a company, usually no.
- Both models in one business, this is the hard case, and it deserves a design session rather than a default.
Decide before the first data load. Retro-fitting a consumer model into a B2B-shaped org is one of the few genuinely large remediation projects on the platform.
2. Master-detail versus lookup
Teams often treat this as a tidiness question. It is not; it is three separate decisions bundled into one field type.
Master-detail gives you roll-up summary fields, cascading delete, and, the important one, child records inherit the parent's sharing. The child has no owner of its own.
That last property is the reason to choose it and the reason to fear it. If access to the child should ever differ from access to the parent, master-detail has already made that impossible.
Ask: does the child ever need its own owner or its own sharing? If yes, use a lookup and build roll-ups another way.
3. External IDs
Every object that receives data from another system needs a unique, external-ID field carrying that system's key, from the first load, not after the first duplicate incident.
Without one, every integration becomes a matching problem: query by name, by email, by some composite that mostly works. Mostly-works matching produces duplicates at a slow, steady rate that nobody attributes to the original decision.
With one, integrations use upsert, which is idempotent, faster, and dramatically simpler to reason about. This is the highest return-on-effort decision on the list and it costs about ten minutes.
4. Record types, and how many
Record types are cheap to add and awkward to remove, because they get referenced by page layouts, picklist availability, automation entry criteria, reports, and permission sets.
The failure mode is using record types for something they are not: as a substitute for a proper object split, or to model a status. A record type should represent a genuinely different business process on the same object.
If two record types share every field, every layout and every process, they are a picklist value.
5. The sharing model, sized for the worst case
The org-wide default is easy to change in a small org and painful in a large one, because tightening it triggers a sharing recalculation across every affected record.
Design against the volume you expect in three years, not the volume in the launch dataset. Ask:
- What is the record count on the widest object at year three?
- How deep is the role hierarchy, and does it reflect data access or the org chart? (These are different things, and modelling the org chart is a common cause of pain.)
- Are there ownership skews, a single user or queue owning a very large share of records?
Ownership skew in particular degrades quietly. It is far cheaper to distribute ownership by design than to redistribute it later.
6. Standard object or custom object
The pull toward a custom object is strong, because a fresh object has no baggage. The cost is everything you give up: standard reporting, standard features, package compatibility, mobile behaviour, and the accumulated platform work that standard objects receive for free.
Use the standard object unless you can articulate specifically what breaks if you do. "It has fields we do not need" is not that reason.
The corollary: if you have a custom object that duplicates a standard one, you have committed to maintaining a parallel implementation of everything the platform would have given you.
7. Where the number lives
For any value that must be right in a report, amount, quantity, score, status, decide whether it is stored, calculated at read time, or calculated on save. Then be consistent.
| Approach | Good for | Cost |
|---|---|---|
| Formula field | Always current, no storage | Cannot be indexed well; adds to CPU on large reports |
| Roll-up summary | Aggregates across master-detail | Only on master-detail; limited functions |
| Stored field, set on save | Reportable, filterable, fast | Must be kept in step; goes stale silently |
| Calculated downstream | Warehouse-grade analytics | Not available in-org for automation |
The mistake is mixing them for the same concept. When one report reads the stored field and another recomputes it, the two disagree, and the resulting trust problem is much harder to fix than the original modelling choice.
How to spend the design time
A day of modelling before the first sprint is worth more than any subsequent week of remediation. Concretely:
- Draw the object diagram, on one page, with relationship types and directions marked.
- For every relationship, write down whether the child needs independent sharing.
- For every object touched by an integration, name the external ID field.
- For the three widest objects, write the expected year-three record count.
- Write down the one line of business meaning for every record type.
None of that is exotic. It is just the set of questions that becomes very expensive to ask late.



