Home / data / salesforce-files-architecture
salesforce-files-architecture
Working with Salesforce Files at the data layer — `ContentVersion` (binary content + version metadata), `ContentDocument` (the shareable parent handle), `ContentDocumentLink` (the sharing / parent-record join), the 2 GB single-file and 10 MB feed-attached limits, the deprecated `Attachment` object, the Classic-only `Document` object, and Files Connect for external sources.
Open the skill folder on GitHub
Salesforce Files Architecture
Salesforce Files is the modern file-storage primitive on the platform, replacing the legacy Attachment object. The data model is more flexible than Attachment (a single file can be linked to many records, versioned, and shared via libraries), and it is more complex (three sObjects participate in every linked-file relationship). LLMs and inexperienced practitioners frequently misunderstand which object holds the binary, which holds the parent link, and how sharing is computed.
This skill is the data-layer walkthrough. It covers the three-object model, the size limits practitioners hit in production, the deprecated objects (Attachment, Document) you may inherit, and Files Connect for external file sources.
The three-object model
A "file" linked to a record involves three sObjects:
| Object | Holds | Cardinality |
|---|---|---|
ContentVersion | The binary content (VersionData), file name, type, and version metadata | One row per version of the file |
ContentDocument | The shareable handle / "file identity" | One row per file (across all versions) |
ContentDocumentLink | The link from the ContentDocument to a parent record | Many rows per file (one per linked record) |
The relationship is:
ContentVersion (binary + version metadata)
|
v
ContentDocument (file identity) <-- ContentDocumentLink --> Account, Case, Custom__c, etc.
^
ContentVersion v2 (later upload of the same file)
When you upload a new file, you insert a ContentVersion. The platform creates the ContentDocument automatically. To link the file to a record, you insert a ContentDocumentLink with LinkedEntityId = recordId, ContentDocumentId = contentDocId, and a ShareType / Visibility.
When you upload a new version of an existing file, insert a ContentVersion with ContentDocumentId set to the existing file's ContentDocument.Id — the platform appends the version.
Size limits
- 2 GB — maximum file size for a single Salesforce File (uploaded
via UI, REST, or SOAP API; subject to edition / license caveats).
- 38 MB — maximum size when uploaded via Lightning component
(
lightning-file-upload) without chunking; larger needs Apex / REST chunked upload. - 10 MB — maximum size for a file attached to a Chatter feed
comment.
- 25 MB — maximum for the legacy
Attachment.Bodyfield, onereason
Attachmentis deprecated.
These limits are platform constraints; some can be raised via Salesforce Support, but expect the defaults in any greenfield design.
Sharing — ShareType and Visibility
ContentDocumentLink carries two fields that determine how a file is shared:
ShareType—'V'(Viewer),'C'(Collaborator),'I'(Inferred / parent-record-driven).
Visibility—'AllUsers'(anyone with parent-record access cansee the file) or
'InternalUsers'(internal users only; Experience Cloud / portal users excluded).
ShareType = 'I' (Inferred) is the most common default — it makes file access mirror the parent record's sharing. 'V' and 'C' override that for explicit grant scenarios.
Deprecated objects you may inherit
Attachment— the legacy object. Body field max 25 MB, noversioning, no multi-record link, no library support. New development should not use it. Migration path: read each Attachment's
Bodyblob, insert asContentVersion, link viaContentDocumentLink, then delete the original Attachment.Document— Salesforce Classic-only object for static org-level documents. Replaced by Files / static resources / CMS for modern UIs.
Files Connect
Files Connect lets a Salesforce org browse / link files that live in external sources (Google Drive, SharePoint, Box, etc.) without copying them into Salesforce storage. Like External Objects for files: the file content stays at the source; Salesforce shows a reference. Auth is via named credential.
Recommended Workflow
- Confirm whether legacy
Attachmentdata exists. QuerySELECT COUNT(Id) FROM Attachment. If non-zero, plan a migration — the object remains supported but is deprecated for new development. - Choose the right object for the use case. Per-record file = ContentVersion + ContentDocumentLink. Org-wide library file = ContentVersion in a Library. External file source = Files Connect.
- Plan the sharing model. Most use cases want
ShareType = 'I'(inferred from parent record). Explicit grants ('V'Viewer or'C'Collaborator) for cross-record sharing. - Size the file storage budget. Salesforce Files counts against File Storage allocation, distinct from Data Storage. Check Setup -> System Overview for the org's file storage and forecast against expected upload volumes.
- For Apex inserts. First insert
ContentVersionwithVersionData = blob, then queryContentDocumentIdfrom the inserted ContentVersion, then insertContentDocumentLinkto link to the record. Three-step pattern, not one. - For SOQL "files attached to this record". Query
ContentDocumentLink WHERE LinkedEntityId = :recordId, then traverse toContentDocumentand (if needed) the latestContentVersion. - Guard against the 2 GB single-file ceiling. For media / video / large datasets above this, use external storage with Files Connect or another integration and link rather than upload.
What This Skill Does Not Cover
| Topic | See instead |
|---|---|
| LWC file upload UI components | lwc/lwc-file-upload-patterns |
| Static resources for LWC bundling | lwc/static-resources |
| Salesforce CMS for marketing content | experience/salesforce-cms-patterns |
| Big-file media streaming use cases | App-layer (S3 + signed URLs, etc.) |