In Apex, an sObject is a special data type that represents a record from a Salesforce database table. Every standard object (Account, Contact, Opportunity, Case) and every custom object (Invoice__c, Project__c) is exposed to Apex as a typed sObject. Working with records means working with sObjects.
The two flavours: specific and generic
Specific sObjects — Account, Contact, MyObject__c — give you compile-time type safety. The compiler validates field names, catches typos, and enforces type correctness.
Account a = new Account(Name = 'Acme', Industry = 'Technology');
a.AnnualRevenue = 5000000;
insert a;
Generic sObject — the base type SObject — lets you work with any record type when the type isn’t known until runtime. You lose compile-time field checking and have to use the dynamic get()/put() API.
SObject record = Schema.getGlobalDescribe()
.get('Account')
.newSObject();
record.put('Name', 'Acme');
record.put('Industry', 'Technology');
insert record;
Generic sObject is the foundation of dynamic Apex — packaged code, reusable utilities, and metadata-driven frameworks that work across multiple object types.
Anatomy of an sObject
Every sObject instance carries:
- A type — accessible via
getSObjectType(), returns aSchema.SObjectTypetoken. - Fields — set/read via dot syntax (
a.Name) or dynamicput()/get(). - Relationships — parent fields navigable via dot syntax (
contact.Account.Name), child relationships via the relationship name (account.Contacts). - An Id (after insert) — the 15- or 18-character record identifier that ties the in-memory sObject to the database row.
sObject in collections
sObjects compose naturally with collections:
List<Account> accounts = [SELECT Id, Name, Industry FROM Account LIMIT 10];
Set<Id> accountIds = new Map<Id, Account>(accounts).keySet();
Map<Id, Account> accountsById = new Map<Id, Account>(accounts);
That new Map<Id, SObject>(list) trick — building a map keyed by record Id directly from a list — is one of the most used patterns in production Apex.
sObject vs SObjectField vs SObjectType
These three are often confused:
| Type | What it represents | Example |
|---|---|---|
SObject (or specific like Account) | A record instance | Account a = new Account(...); |
Schema.SObjectType | A token for the object’s type | Account.SObjectType |
Schema.SObjectField | A token for a single field | Account.Name.getDescribe() |
The token types are how Apex talks about schema metadata without instantiating actual records — you’ll see them in dynamic queries, FLS checks, and trigger handler frameworks.
Field-level security and CRUD
sObject access in Apex respects the running user’s object permissions when you call methods like Security.stripInaccessible() or use WITH SECURITY_ENFORCED in SOQL. By default, raw sObject manipulation in Apex does not enforce FLS — that’s the developer’s responsibility, and it’s the most common cause of failed security reviews on AppExchange packages.
What interviewers are really looking for
A junior answer says “an sObject is a Salesforce record.” A senior answer adds three things: that there’s a generic SObject base type used in dynamic Apex, that collections of sObjects are the foundation of bulkification, and that FLS/CRUD enforcement on sObjects is the developer’s responsibility. Mention Schema.SObjectType and getDescribe() and you’ve shown you’ve worked beyond the trivial CRUD path.
Verified against: Apex Developer Guide — Working with sObjects. Last reviewed 2026-05-17 for Spring ‘26 release.