Skip to main content

SF-0280 · Concept · Medium

Can you tell me about a few objects which do not support DML operations?

✓ Verified by Vikas Singhal · Last reviewed 5/17/2026 · Updated for Spring '26

A handful of Salesforce objects look like normal SObjects when you query them, but they reject DML — insert, update, delete, or some combination. Trying anyway throws a runtime System.SObjectException like “DML operation Insert not allowed on AggregateResult.”

The list breaks into three buckets: query-only synthetic objects, system-managed objects with restricted DML, and read-only system objects.

Bucket 1: Query-only synthetic objects

These aren’t real records — they’re aggregates or virtual rows the platform builds at query time.

ObjectWhy no DML
AggregateResultResult of GROUP BY/aggregate queries. Synthetic — has no underlying row.
DescribeSObjectResult / Schema.DescribeFieldResultSchema metadata — read-only by definition.
OpportunityFieldHistory, AccountHistory, etc. (*History)Audit trail rows — Salesforce writes them; you don’t.
RecordTypeDefined in Setup. Visible via SOQL but not editable through DML.
BusinessProcess, RecordTypeLocalizationSetup-defined.
LoginHistoryGenerated by the platform on each login.
UserRecordAccessCalculated at query time, never stored.
List<AggregateResult> ar = [SELECT COUNT(Id) cnt FROM Account];
// insert ar; // System.SObjectException: DML not allowed on AggregateResult

Bucket 2: System-managed with partial DML

Some objects support some DML operations but not others.

ObjectAllowedForbidden
ApexClass, ApexTriggerCreated via Tooling API or metadata deployNo direct insert in Apex
ProfileUpdatable via Tooling APINo insert or delete in Apex on standard profiles
UserLicenseReadNot assignable via DML
LoginHistoryReadNo DML
EmailMessageInsert (via inbound email or platform)Updates and deletes restricted
Knowledge__kav (Salesforce Knowledge)Insert / Update (with conditions)Standard delete only on archived versions
FlowInterviewCreated by Flow runtimeNo direct insert from user code

These are platform-managed lifecycles — the system creates and retires them, not you.

Bucket 3: External and Big Objects

ObjectDML behaviour
External objects (__x)DML depends on the OData connection — many are read-only
Big Objects (__b)Use Database.insertImmediate() instead of insert; no update, no delete (replaced with a new insert)
Custom Metadata (__mdt)No DML at all in Apex — use Metadata.Operations.enqueueDeployment() (a metadata API call, not DML)

Big Objects are an especially common interview gotcha because they look like normal custom objects (MyBigObj__b) but use a different API:

MyBigObj__b row = new MyBigObj__b(...);
// insert row;                         // SObjectException
Database.insertImmediate(new List<MyBigObj__b>{ row }); // correct

Custom Metadata Types — the really common gotcha

You can read MyConfig__mdt records freely with SOQL. You cannot insert or update them with insert/update. To modify, you go through the metadata API via Metadata.Operations.enqueueDeployment() — async, requires the Metadata API permission, returns a deployment Id.

List<MyConfig__mdt> rows = [SELECT Id, Threshold__c FROM MyConfig__mdt];
// update rows;  // SObjectException — no DML on __mdt

This is by design: Custom Metadata is meant to be deployed between orgs as configuration, not edited transactionally.

How to find out for a given object

Use Schema describe:

Schema.DescribeSObjectResult d = MyObject__c.SObjectType.getDescribe();
System.debug('Creatable:  ' + d.isCreateable());
System.debug('Updatable:  ' + d.isUpdateable());
System.debug('Deletable:  ' + d.isDeletable());
System.debug('Undeletable: ' + d.isUndeletable());

The four boolean methods on DescribeSObjectResult are the authoritative source. They reflect FLS for the running user plus the platform’s intrinsic restrictions.

What interviewers are really looking for

The naming check: AggregateResult, Custom Metadata, History objects. The senior signal is: (1) distinguishing query-only synthetic objects (AggregateResult, *History) from platform-managed lifecycles (Profile, ApexClass) from special APIs (Big Objects via insertImmediate, Custom Metadata via Metadata.Operations), (2) the isCreateable/isUpdateable/isDeletable describe methods as the runtime check, (3) Custom Metadata edits go through the Metadata API, not DML — surprises a lot of mid-level devs.

Verified against: Apex Developer Guide — DML Operations, Big Object Storage. Last reviewed 2026-05-17.