agentleFS
jiten-singh-shahijiten-singh-shahi/salesforce-claude-code/.cursor/skills/sf-data-modeling/SKILL.md

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.

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
  1. Distinctive:

    No roll-up summaries needed

    line 63
  2. Distinctive:

    Start with Private OWD for sensitive objects and open up with sharing rules.

    line 181
  3. Distinctive:

    Add external ID fields on objects queried by non-Id values

    line 212
  4. Distinctive:

    Consider skinny tables for frequently-accessed field subsets

    line 214
  5. Distinctive:

    Avoid Roll-Up Summary fields on LDV child objects (use batch triggers instead)

    line 215
  6. Distinctive:

    Add meaningful fields to the junction (Role, Start Date, Status)

    line 241
  7. Very specific:

    Use AccountContactRelation (standard) before creating custom junctions for Account-Contact

    line 242

≈ “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.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

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 NeedUse Standard ObjectNot Custom
Customer companiesAccountCompany__c
Individual contactsContactPerson__c
Sales dealsOpportunityDeal__c
Support ticketsCaseTicket__c
Events/meetingsEventMeeting__c
Tasks/to-dosTaskTodo__c
Products/pricingProduct2, PricebookEntryProduct__c
OrdersOrder, OrderItemPurchaseOrder__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

RelationshipCascade DeleteRoll-Up SummaryRequiredSharing Inherited
LookupNo (configurable)NoNoNo
Master-DetailYesYesYesYes
Many-to-Many (Junction)Both sidesFrom junctionBothFrom primary master
HierarchicalNoNoNoNo
External LookupNoNoNoNo

*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 TypeUse WhenAvoid When
Text (255)Short single-line textLong descriptions
Long Text AreaUp to 131,072 charsNeed to filter/search on it
Rich Text AreaHTML-formatted contentNeed to query/filter by content
NumberIntegers, no currencyFinancial values (use Currency)
CurrencyMonetary valuesNon-financial numbers
DateDate without timeNeed time zone info
DateTimeTimestamps, audit trailsSimple date records
CheckboxBoolean yes/noOptional boolean (use Picklist)
Picklist (single)Controlled vocabularyMany values (use Lookup)
Picklist (multi)Multiple selectionsFiltering/reporting (anti-pattern)
FormulaCalculated, read-onlyValues needing DML update
Roll-Up SummaryAggregate child data25 per object (default limit)
External IDUpsert 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 tagging

Custom Metadata Types vs Custom Settings vs Custom Labels

FeatureCustom MetadataCustom SettingsCustom Labels
DeployableYesNo (hierarchy)/Yes (list)Yes
Per-user/profile valuesNoYes (hierarchy)No
Governor limit on readsNo (cached)Yes (SOQL equivalent)No
Best forConfig deployed with codeUser/profile-specific settingsTranslatable 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 SettingOther UsersBest For
Public Read/WriteRead + WriteReference/config data
Public Read OnlyRead onlyProducts, pricebooks
PrivateNoneAccounts, Opportunities
Controlled by ParentInheritsMaster-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

AdapterUse When
OData 2.0/4.0External REST API with OData support
Custom AdapterProprietary API or database
Cross-OrgAnother Salesforce org

External Objects have no triggers, Flows, or Validation Rules. Use Apex callouts for write operations.


Anti-Patterns

Anti-PatternFix
Polymorphic lookup abuseUse explicit lookup fields per related object
Over-normalizationFlatten into fields unless multiple addresses per record
Too many custom fields (800 limit)Split into related child objects
Circular Master-DetailBreak the circle with a Lookup on one side
Text instead of LookupUse Lookup fields for referential integrity
Ignoring LDV on 100K+ objectsRequest custom indexes, use skinny tables

Related

  • Agent: sf-architect — For interactive, in-depth guidance
  • Constraints: sf-apex-constraints — Governor limits and Apex safety rules

Download now (ZIP)

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
What did you use it for? e.g. Reviewing pull requests in a Rails app

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.