sf-data-modeling
Skill15 starsChanged 7 months agoMITView on GitHub
Use when designing Salesforce custom objects, relationships, Custom Metadata, or sharing models for scalable org architecture. Do NOT use for SOQL optimization or Apex patterns.
In this repository58 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- asideSkill
- checkpointSkill
- configure-sccSkill
- continuous-agent-loopSkill
- mcp-server-patternsSkill
- model-routeSkill
- prompt-optimizerSkill
- refactor-cleanSkill
- resume-sessionSkill
- save-sessionSkill
- search-firstSkill
- security-scanSkill
- sessionsSkill
- sf-2gp-security-reviewSkill
- sf-agentforce-developmentSkill
- sf-agentforce-mcp-actionsSkill
- sf-apex-async-patternsSkill
- sf-apex-best-practicesSkill
- sf-apex-constraintsSkill
- sf-apex-cursorSkill
- sf-apex-enterprise-patternsSkill
- sf-apex-testingSkill
- sf-api-designSkill
- sf-approval-processesSkill
- sf-aura-developmentSkill
- sf-build-fixSkill
- sf-cli-referenceSkill
- sf-debuggingSkill
- sf-deployment-constraintsSkill
- sf-deploymentSkill
- sf-devops-ci-cdSkill
- sf-docs-lookupSkill
- sf-e2e-testingSkill
- sf-experience-cloudSkill
- sf-flow-developmentSkill
- sf-governor-limitsSkill
- sf-harness-auditSkill
- sf-helpSkill
- sf-integrationSkill
- sf-lwc-constraintsSkill
- sf-lwc-developmentSkill
- sf-lwc-testingSkill
- sf-metadata-managementSkill
- sf-platform-events-cdcSkill
- sf-quickstartSkill
- sf-security-constraintsSkill
- sf-securitySkill
- sf-soql-constraintsSkill
- sf-soql-optimizationSkill
- sf-tdd-workflowSkill
- sf-testing-constraintsSkill
- sf-trigger-constraintsSkill
- sf-trigger-frameworksSkill
- sf-visualforce-developmentSkill
- strategic-compactSkill
- update-docsSkill
- update-platform-docsSkill
The file
We split this skill into the rules it gives an agent
7 rules. About 0 are common, 6 are distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈6
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 63
No roll-up summaries needed
- Distinctive: line 181
Start with Private OWD for sensitive objects and open up with sharing rules.
- Distinctive: line 212
Add external ID fields on objects queried by non-Id values
- Distinctive: line 214
Consider skinny tables for frequently-accessed field subsets
- Distinctive: line 215
Avoid Roll-Up Summary fields on LDV child objects (use batch triggers instead)
- Distinctive: line 241
Add meaningful fields to the junction (Role, Start Date, Status)
- Very specific: line 242
Use AccountContactRelation (standard) before creating custom junctions for Account-Contact
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Salesforce Data Modeling
@../_reference/DATA_MODELING.md
When to Use
- Designing new custom objects, fields, or relationships
- Deciding between lookup vs master-detail relationships
- Planning record types, page layouts, or sharing model architecture
- Architecting for large data volumes (LDV) requiring index-aware field design
- Reviewing or refactoring an existing data model
- Evaluating external objects, custom metadata types, or hierarchical settings
Object Design Principles
Extend Standard Objects When Possible
| Business Need | Use Standard Object | Not Custom |
| Customer companies | Account | Company__c |
| Individual contacts | Contact | Person__c |
| Sales deals | Opportunity | Deal__c |
| Support tickets | Case | Ticket__c |
| Events/meetings | Event | Meeting__c |
| Tasks/to-dos | Task | Todo__c |
| Products/pricing | Product2, PricebookEntry | Product__c |
| Orders | Order, OrderItem | PurchaseOrder__c |
Standard objects come with built-in reports, process automations, and integrations.
Custom Object Naming
API Name: ProjectTask__c (PascalCase + __c)
Label: Project Task (human-readable)
Plural: Project Tasks
Relationship Name: ProjectTasks (plural for child relationship)Relationship Types
| Relationship | Cascade Delete | Roll-Up Summary | Required | Sharing Inherited |
| Lookup | No (configurable) | No | No | No |
| Master-Detail | Yes | Yes | Yes | Yes |
| Many-to-Many (Junction) | Both sides | From junction | Both | From primary master |
| Hierarchical | No | No | No | No |
| External Lookup | No | No | No | No |
*Master-Detail can be reparented if "Allow Reparenting" is enabled.
When to Use Lookup
- Child can exist independently (Contact without Account)
- No roll-up summaries needed
- Child needs its own sharing settings
- Multiple lookups, none is primary
When to Use Master-Detail
- Child has no meaning without parent (Order Line Item without Order)
- Roll-up summary fields needed on parent
- Child deleted when parent deleted
- Child sharing inherits from parent
<!-- Master-Detail field metadata -->
<fields>
<fullName>Project__c</fullName>
<label>Project</label>
<type>MasterDetail</type>
<referenceTo>Project__c</referenceTo>
<relationshipLabel>Project Tasks</relationshipLabel>
<relationshipName>ProjectTasks</relationshipName>
<relationshipOrder>0</relationshipOrder>
<reparentableMasterDetail>false</reparentableMasterDetail>
</fields>Field Type Guide
| Field Type | Use When | Avoid When |
| Text (255) | Short single-line text | Long descriptions |
| Long Text Area | Up to 131,072 chars | Need to filter/search on it |
| Rich Text Area | HTML-formatted content | Need to query/filter by content |
| Number | Integers, no currency | Financial values (use Currency) |
| Currency | Monetary values | Non-financial numbers |
| Date | Date without time | Need time zone info |
| DateTime | Timestamps, audit trails | Simple date records |
| Checkbox | Boolean yes/no | Optional boolean (use Picklist) |
| Picklist (single) | Controlled vocabulary | Many values (use Lookup) |
| Picklist (multi) | Multiple selections | Filtering/reporting (anti-pattern) |
| Formula | Calculated, read-only | Values needing DML update |
| Roll-Up Summary | Aggregate child data | 25 per object (default limit) |
| External ID | Upsert key from external system | - |
Multi-Select Picklist Warning
// Limited SOQL support — can use INCLUDES/EXCLUDES but not = or IN
List<Case> cases = [
SELECT Id FROM Case
WHERE Tag_List__c INCLUDES ('Billing', 'Technical')
];
// Cannot use in GROUP BY, ORDER BY, or most aggregates
// Consider Lookup to a Tags junction object for complex taggingCustom Metadata Types vs Custom Settings vs Custom Labels
| Feature | Custom Metadata | Custom Settings | Custom Labels |
| Deployable | Yes | No (hierarchy)/Yes (list) | Yes |
| Per-user/profile values | No | Yes (hierarchy) | No |
| Governor limit on reads | No (cached) | Yes (SOQL equivalent) | No |
| Best for | Config deployed with code | User/profile-specific settings | Translatable strings |
// Custom Metadata — no SOQL limits, deployable
String endpoint = Service_Config__mdt.getInstance('Production').Endpoint_URL__c;
// Custom Setting — profile-specific
Boolean isEnabled = Integration_Settings__c.getInstance().Is_Enabled__c;
// Custom Label — translatable
String welcomeMsg = System.Label.Welcome_Message;Record Types
When to Use
- Different page layouts per user group
- Different picklist values per business process
- Different automation processes per record type
When NOT to Use
- Simple field-level differences (use conditional visibility)
- Access control (use sharing rules or permission sets)
- Fundamentally different data structures (use separate objects)
Id caseRecordTypeId = Schema.SObjectType.Case.getRecordTypeInfosByDeveloperName()
.get('Internal_Support').getRecordTypeId();
List<Case> internalCases = [
SELECT Id, Subject FROM Case
WHERE RecordTypeId = :caseRecordTypeId WITH USER_MODE
];Sharing Model Design
Object-Wide Defaults (OWD)
| OWD Setting | Other Users | Best For |
| Public Read/Write | Read + Write | Reference/config data |
| Public Read Only | Read only | Products, pricebooks |
| Private | None | Accounts, Opportunities |
| Controlled by Parent | Inherits | Master-Detail children |
Start with Private OWD for sensitive objects and open up with sharing rules.
Apex Managed Sharing
public with sharing class ProjectSharingService {
public static void shareProjectWithUser(Id projectId, Id userId, String accessLevel) {
Project__Share shareRecord = new Project__Share(
ParentId = projectId,
UserOrGroupId = userId,
AccessLevel = accessLevel,
RowCause = Schema.Project__Share.RowCause.Manual
);
Database.SaveResult result = Database.insert(shareRecord, false);
if (!result.isSuccess() &&
result.getErrors()[0].getStatusCode() != StatusCode.FIELD_FILTER_VALIDATION_EXCEPTION) {
throw new SharingException('Failed to share: ' + result.getErrors()[0].getMessage());
}
}
public class SharingException extends Exception {}
}Large Data Volume (LDV) Considerations
Objects with >100,000 records require special attention.
Schema design:
- Add external ID fields on objects queried by non-Id values
- Request custom indexes on fields used in WHERE clauses
- Consider skinny tables for frequently-accessed field subsets
- Avoid Roll-Up Summary fields on LDV child objects (use batch triggers instead)
// Good — uses indexed fields, selective
List<Order__c> orders = [
SELECT Id, Status__c FROM Order__c
WHERE AccountId = :accountId
AND CreatedDate >= :thirtyDaysAgo
LIMIT 200
];Archiving: Move old records to BigObjects or external archive. Use batch jobs for archive-and-delete.
Junction Object Patterns
Account <-- AccountContactRelation --> Contact
+ Role (picklist)
+ IsPrimary (checkbox)
+ StartDate (date)- Junction objects with Master-Detail on both sides inherit sharing from BOTH parents
- Add meaningful fields to the junction (Role, Start Date, Status)
- Use
AccountContactRelation(standard) before creating custom junctions for Account-Contact
External Object Patterns
| Adapter | Use When |
| OData 2.0/4.0 | External REST API with OData support |
| Custom Adapter | Proprietary API or database |
| Cross-Org | Another Salesforce org |
External Objects have no triggers, Flows, or Validation Rules. Use Apex callouts for write operations.
Anti-Patterns
| Anti-Pattern | Fix |
| Polymorphic lookup abuse | Use explicit lookup fields per related object |
| Over-normalization | Flatten into fields unless multiple addresses per record |
| Too many custom fields (800 limit) | Split into related child objects |
| Circular Master-Detail | Break the circle with a Lookup on one side |
| Text instead of Lookup | Use Lookup fields for referential integrity |
| Ignoring LDV on 100K+ objects | Request custom indexes, use skinny tables |
Related
- Agent:
sf-architect— For interactive, in-depth guidance - Constraints:
sf-apex-constraints— Governor limits and Apex safety rules
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

