Getting started with Salesforce object relationships
When you're designing a data model, Salesforce object relationships are the first thing to get right. The link you choose dictates how your sharing model works, how you'll write your SOQL queries, and whether you can use roll-up summary fields. Get this wrong early and you'll be fighting against the platform for the rest of the project.
I've seen plenty of developers treat every connection like a standard foreign key from the SQL world. In Salesforce, the type of link you choose has massive implications for record ownership and security.
The two heavy hitters of Salesforce object relationships
1. Lookup relationship
Think of a Lookup as a loose link. It's the most common type of connection you'll use, and it basically says, "This record is related to that record, but they're both independent adults." If you delete the parent, the child usually just hangs around with a blank field, though you can change that behavior.
Most of the relationships you build will be lookups, because they're flexible. One thing that trips people up is Salesforce data skew. If you have ten thousand contacts all looking up to one single "Generic Account," you're going to see some serious performance lag during updates. I always tell my team to watch out for that during the design phase.
2. Master-Detail relationship
This is a much tighter bond. In a Master-Detail setup, the "Detail" (child) record is completely dependent on the "Master" (parent), and the parent calls all the shots:
- The child record doesn't have its own owner. It just inherits whatever the parent has.
- If you delete the parent, the child is gone too. No questions asked.
- You get access to Roll-up Summary fields. This is usually the main reason people choose Master-Detail over a Lookup.
Pro Tip: You can't create a Master-Detail relationship on an object that already has data unless you create a Lookup first, fill it with data for every record, and then convert it. It's a bit of a pain, so try to decide this before you go live.

A technical schema diagram illustrating a many-to-many relationship using a central junction object connected to two parent objects.
3. Many-to-many (junction objects)
Sometimes you need a record to relate to many things at once. Think of a "Student" and a "Class." A student has many classes, and a class has many students. You can't do that with a simple field, so you need a "Junction Object" in the middle.
To build this, you create a custom object (like "Enrollment") and give it two Master-Detail fields, one pointing to each parent. It's a clean way to model complex data without making your Salesforce objects messy with redundant data.
Advanced and special relationship types
Self and hierarchical relationships
A Self-Relationship is just a lookup that points back to the same object. I use this all the time for things like "Parent Account" or "Original Case." The Hierarchical Relationship is a special version used only on the User object, mostly so you can define a manager-subordinate chain for approvals.
Polymorphic relationships
These are the weird ones. A polymorphic field can point to more than one type of object. Think of the "WhoId" on a Task: it could be a Lead or a Contact. You can't just use standard dot notation in SOQL for these. You usually have to use TYPEOF if you're querying them in Apex, which can get a bit wordy.
SELECT Id, Subject,
TYPEOF Who
WHEN Contact THEN Name, Email
WHEN Lead THEN Name, Company
END
FROM Task
External and indirect lookups
If you're using Salesforce Connect to bring in data from an outside system (like an ERP), you'll use these. An External Lookup links a child to an external parent. An Indirect Lookup does the opposite: it links a standard Salesforce child to an external parent using an External ID. It's handy because you don't have to sync all that data into Salesforce storage.
Comparing different Salesforce object relationships
Here is how the two stack up on the differences you'll run into in a real org.
| Feature | Lookup | Master-Detail |
|---|---|---|
| Ownership | Independent | Inherited from Master |
| Deletion | Optional (Keep or Delete) | Cascade Delete (Child dies too) |
| Roll-up Summaries | No (Unless using DLRS) | Yes |
| Required? | Optional | Always Required |
Working with relationships in code and queries
When you're writing SOQL, you'll use dot notation to go "up" the chain (child to parent) and subqueries to go "down" (parent to child). Here's how that looks in practice.
Going up, from child to parent:
SELECT Name, Account.Name, Account.Industry FROM Contact
Going down, from parent to child:
SELECT Name, (SELECT LastName FROM Contacts) FROM Account
One thing to keep in mind: when you're deciding between Apex vs Flow for your logic, remember that Master-Detail relationships can trigger some heavy automation when parents are updated. Always test your triggers for bulk processing.
Key takeaways
- Use a Lookup if you want the records to stay independent and have their own owners.
- Go with Master-Detail if the child record shouldn't exist without the parent, or if you need native roll-up summaries.
- Junction objects are your best friend for many-to-many scenarios.
- Watch out for data skew when creating lookups to a single "hub" record.
- Polymorphic fields like
WhoIdrequire special handling in your SOQL queries.
The bottom line
Getting your Salesforce object relationships right from the start saves you a massive headache later. I've spent too many weekends refactoring data models because a client realized six months in that they actually needed roll-up summaries on a lookup relationship. Map out your sharing and deletion requirements before you start clicking "New Field." It pays off.
Leave a Comment