Attachment
An Attachment is a standard Salesforce object that stores a single file (a PDF, image, or document) tied directly to one parent record.
Definition
An Attachment is a standard Salesforce object that stores a single file (a PDF, image, or document) tied directly to one parent record. The Attachment row holds the binary content in its Body field as a blob, along with metadata like the file name, content type, body length, and the parent record ID. Files attached this way show up in the Notes & Attachments related list on the parent record and can be downloaded or viewed, but not much else.
Attachment is the older file mechanism. It came before Salesforce Files, the modern feature built on the ContentVersion and ContentDocument objects. The object is still available in every org for backward compatibility, and existing Apex that creates Attachment rows still runs. Salesforce now points new development at Files, and Lightning record pages surface Files by default. Treat Attachment as a legacy term: when you see it in older docs or inherited code, the current equivalent is almost always Files.
Attachment from object schema to migration
The Attachment object and its fields
The Attachment standard object is deliberately small. ParentId points to the record the file belongs to, and it is set once at insert because Attachment is not reparentable. Body holds the binary file content as a Blob. Name carries the file name, ContentType records the MIME type (for example application/pdf), and BodyLength reports the size in bytes. IsPrivate marks an Attachment as visible only to its owner and admins. OwnerId is the user who created the row. One Attachment record equals exactly one file on exactly one parent. There is no concept of a separate join object, because the link to the parent is the single ParentId lookup. The maximum size for a single Attachment Body is 25 MB when uploaded through a form, and a bit higher through the API after base64 encoding overhead. Because the file lives inside the same row as its metadata, editing the Body replaces the file in place with no record of the previous content. That simplicity is the whole point of the object, and also its biggest limitation compared to Files.
Attachments next to Salesforce Files
Salesforce Files splits the same job across three objects. ContentVersion stores each version of a file, ContentDocument represents the file as a whole, and ContentDocumentLink associates that file with one or more records and users. That structure buys real capabilities. A single Files document can be shared to a Lead, an Opportunity, and a Case at once, while an Attachment can only ever belong to one parent. Files keep version history, so uploading a revised contract preserves the earlier draft. Files appear in Files Home, in Chatter, and in the Salesforce mobile app, and they support followers and richer sharing controls. The official comparison is blunt about the gap: Attachments only support download and view, while Files add versions, sharing, and previews. Attachments have none of the collaboration features that teams now expect. This is why the object sits in maintenance mode and why most new file requirements should map to ContentVersion rather than Attachment.
Why Salesforce moved to Files
The Attachment model fit an earlier era when each record simply needed its own file. A quote PDF lived on one Opportunity, and that was enough. Real work outgrew that shape. Teams needed one proposal shared across several records, a clear history of revisions, and a single place to manage every document in the org. Attachment answers none of those needs. Rather than bolt versioning and cross-record sharing onto a single-row object, Salesforce built Files as a separate, layered model and shifted investment there. New features, mobile support, and Lightning enhancements landed on Files, and Attachment stopped receiving meaningful updates. The object was kept alive so existing data and integrations would not break, which is the usual Salesforce pattern for legacy features. The practical result for anyone building today is straightforward. Files is the default and recommended path, and Attachment is the compatibility layer you maintain rather than the tool you reach for first.
Where Attachments still turn up
Even in orgs that prefer Files, Attachments linger in predictable spots. Custom objects whose page layouts still include the Notes & Attachments related list keep exposing the old upload path, often because nobody updated the layout when Files arrived. Inbound email is another source. Email-to-Case and inbound email handlers can store attachments as Attachment records or as Files depending on org settings, and that setting drifts over time. Older Apex, triggers, and managed packages that were written against the Attachment object continue to create rows long after the org adopted Files everywhere else. Data migrations and legacy integrations sometimes target Attachment because that is what the source system mapped to years ago. None of this is broken, but it means a single org can hold files in two different models at once. Knowing where Attachments hide makes cleanup and reporting far less surprising, and it explains why an org can show files in places Files Home never lists.
Storage, querying, and Apex
Attachments consume File Storage in the org, drawing from the same shared pool that Files use. That shared ledger matters during migration: moving an Attachment to Files does not free space, because the file lands in the same bucket. Migration is about features and user experience, not capacity. On the developer side, Attachment behaves like any standard object. You can query it with SOQL, for example SELECT Id, Name, ContentType, BodyLength, ParentId FROM Attachment WHERE ParentId = :recordId, and Apex can create, read, update, and delete rows. The Body field returns a Blob, and EncodingUtil.base64Encode is the usual step before sending the content through a REST callout or returning it to a client. One quirk catches people: a ParentId can point to many object types, so a query filtered only by ParentId may span Accounts, Cases, and custom objects unless you constrain it further. Code that processes Attachments should not assume a single parent type.
Migrating Attachments to Files
Converting Attachments to Files is a well-trodden path with documented patterns and partner tools. The mechanics are consistent. For each Attachment you create a ContentVersion from its Body, which produces a ContentDocument, then you insert a ContentDocumentLink that points the new document at the original ParentId. That preserves the association so users still find the file on the same record. Custom Apex batch jobs handle large volumes, and several AppExchange utilities do the same with less code. Sequence the work carefully. Run the conversion in manageable batches and reconcile record counts after each one, because debugging a partial migration is far easier at small scale. Update any Apex, Flows, or integrations that reference the Attachment object in the same release that moves the data, so code and data change together. After the files are safely in Files, remove the Notes & Attachments related list from the affected layouts. That is the gentle way to retire the old path without aggressively deleting historical data that reports or integrations might still read.
How to create an Attachment (and the Files alternative)
You rarely create Attachments by hand in modern Salesforce, but it still happens through Data Loader, the API, or Apex when you maintain a legacy object or integration. Here is the shape of creating one, with the strong caveat that new file work should target Salesforce Files (ContentVersion) instead.
- Confirm the parent supports it
Check that the parent object has the Notes & Attachments related list on its page layout. Without it, users will not see the Attachment in the UI even though the row exists. If the object already uses Files, prefer that path instead of adding the legacy related list back.
- Build the record with required fields
Create an Attachment with Name, Body, and ParentId set. Body must be a Blob, so encode or read your file content into a Blob first. ContentType is optional but helps the browser render or download the file correctly.
- Insert and verify on the record
Insert the Attachment through Apex DML, Data Loader, or the REST API. Open the parent record and confirm the file appears under Notes & Attachments and downloads as expected.
- Plan the Files equivalent
For anything beyond a one-off legacy need, create a ContentVersion and a ContentDocumentLink instead. That gives you versioning, multi-record sharing, and visibility in Files Home and mobile that an Attachment can never provide.
The file name shown to users, for example proposal.pdf. Include the extension so the file opens with the right app.
The binary file content as a Blob. Single uploads cap at 25 MB; encode file bytes to a Blob before insert.
The Id of the record the file attaches to. Set once at insert because Attachment cannot be reparented later.
- An Attachment belongs to exactly one parent. If you need the same file on several records, use Files, not multiple Attachment copies.
- Editing the Body overwrites the file with no version history. The previous content is gone, unlike a ContentVersion.
- Attachments do not appear in Files Home, Chatter, or the mobile app, so users accustomed to Files may not find them.
Prefer this walkthrough as its own page? How to Attachment in Salesforce, step by step
Trust & references
Cross-checked against the following references.
Straight from the source - Salesforce's reference material on Attachment.
Hands-on resources to go deeper on Attachment.
About the Author
Dipojjal Chakrabarti is a B2C Solution Architect with 29 Salesforce certifications and over 13 years in the Salesforce ecosystem. He runs salesforcedictionary.com to help admins, developers, architects, and cert/interview candidates sharpen their fundamentals. More about Dipojjal.
Discussion
Loading discussion…