TL;DR 30-second summary
Dynamics 365 stores attachments in the Dataverse by default. That’s fine… until it isn’t. As your file storage grows, so do your costs and complexity. To keep your environment lean, you’d want to consider Dynamics 365 attachment offloading, which generally has two paths: offload them manually using Power Automate (potentially free and flexible, but often fiddly to maintain) or deploy a dedicated solution like CB Dynamics 365 Seamless Attachment Extractor (paid, self-contained, and zero-maintenance).
This guide helps you determine which path suits your environment, providing the technical depth you need to make an informed call.
Start Here: Should you build your own solution (a DIY approach)?
Before writing a single flow action, answer these four questions. They won’t make the decision for you, but they’ll make the right choice for you much more obvious.
| Question | Yes → consider DIY | No → consider managed |
| Do you have < 100 new attachments/day on average? | Flow run limits unlikely to bite | Quota throttling is a real risk with flows queuing or silently skipping |
| Do you have a Power Platform engineer who owns this long-term? | Someone will be there when connectors re-auth or solutions break | This becomes an unowned dependency the moment the builder moves on |
| Can your users tolerate a brief async delay before the link appears? | Async flows are fine — users navigate to docs a few seconds later | Race conditions produce broken attachment icons and support tickets |
| Is your storage requirement straightforward (one tenant, one site)? | Standard flow connectors will cover it | Multi-BU routing, Azure Blob, or Azure File needs custom logic fast |
| No historical attachments to migrate? | No need to worry about how long it would take to move them | Estimate the cost and time to move historical files, it is likely more acceptable in a managed scenario |
NOTE:
Five ‘Yes’ answers?
DIY a reasonable path. Read the next section for the implementation and its known rough edges.
Mixed answers?
Consider the dedicated solution first. The comparison table at the end is for you.
The DIY Path: Power Automate
Let’s say you want to move the file attachments stored in the note entity of your Dynamics (Annotation) to SharePoint for better management and storage optimization. Here’s how you can accomplish this using Power Automate (Cloud flows).
1. Trigger: When a New or Updated Attachment is Created
We begin with the Dataverse trigger, set to fire whenever a note (Annotation) is added or modified with a file attachment.
Power Automate Action Configuration 1: Trigger Setup
Trigger action: "When a row is added, modified or deleted" Table name: Annotations Change type: Added or Modified Advanced options > Filter expression: isdocument eq true // Only process notes that are file attachments // Optionally, you can filter on regardingobjectid, etc.
What it does:
Starts the flow when a file-type note is created or updated.
Limitations:
- If attachments are frequently updated or overwritten, multiple flows could run for the same file.
- Filtering solely on isdocument eq true will apply to all attachments—refine as needed.
2. List Relevant Attachments for the Record
It’s often useful to process all files related to a particular record (e.g., all attachments for an Opportunity or Case).
Power Automate Action Configuration 2: List Attachments
Action: "List rows" (Dataverse)
Table name: Annotations
Filter Rows:
_objectid_value eq {Dynamic value: Regarding record GUID from trigger}
and isdocument eq true
Select Columns:
annotationid, filename, mimetype, documentbody, filesize, objectid,
objecttypecode
What it does:
Retrieves all file attachments related to the triggered record, with essential metadata and the Base64-encoded file content (documentbody).
Limitations:
- documentbody is available directly if included in Select Columns; otherwise, a separate retrieval step may be needed.
- Max row limits apply; use paging for more than 5,000 records.
3. Loop Through Each Attachment
Power Automate Action Configuration 3: Apply to Each
Action: "Apply to each" Input: value from "List rows"
What it does:
Iterates over all the attachments found.
Limitation:
- Power Automate has limits on concurrency and throughput.
- Large attachments may incur performance or timeout issues.
4. Get or Prepare the File Content
When working with file attachments in Dataverse’s Annotation (note) entity, the file content is stored in a field called documentbody. This content is Base64-encoded, so it’s not directly usable as a file until it’s decoded.
When you use the List rows action, you can optionally include the documentbody column in the list of columns to retrieve. If you do, the file’s Base64 content will already be present in your output. In this case, you do not need to perform an additional fetch and can use the documentbody field in subsequent steps.
However, if you did not include documentbody in your List rows action, you will need to retrieve it for each note as presented below.
Power Automate Action Configuration 4: Get File Content (if necessary)
Inside Apply to each:
Action: Get a row by ID (Dataverse) Table name: Annotations Row ID: annotationid
Use documentbody from this output.
What it does:
- Retrieves the full annotation record for each attachment, including the documentbody field, which contains the actual file content in Base64.
- This is necessary if your “List rows” action did not include documentbody in its selected columns.
- The returned documentbody can then be decoded and used for saving the file to SharePoint or another location.
Limitations:
- Additional API calls: Each file triggers an individual Dataverse request, which can impact performance and API quota if processing many attachments.
- File size constraints: Dataverse has a maximum attachment size limit of 5 to 128 MB, depending on version and configuration, and Power Automate’s HTTP payload limit may cause the connector to struggle or fail before that ceiling is reached.
5. Convert and Save Attachment to SharePoint
You must decode the Base64 to binary before saving.
Power Automate Action Configuration 5: Decode and Create File
Inside Apply to each:
Action: Compose
Expression: base64ToBinary(items('Apply_to_each')?['documentbody'])
Action: "Create file" (SharePoint)
Site Address: [Your site URL]
Folder Path: [Your folder]
File Name: filename
File Content: Outputs from Compose (binary data)What it does:
Converts Base64 file content to binary, and creates a file in SharePoint.
Limitations:
- If the destination file with the same name exists, this will overwrite it.
- Document move will fail if SharePoint/OneDrive is offline or rate-limited.
- User must have permission to create files at the target location.
Note:
You should wrap this step and the following in a Scope action with a “Configure run after” error branch, so the deletion only fires on successful placement in SharePoint.
6. Delete the Original Attachment to Free Storage
After safely moving your file to SharePoint, this step clears the file content from the note while preserving the text of the note and metadata. This ensures you maintain context and audit history, all while saving Dataverse storage and indicating where the attachment has gone.
Power Automate Action Configuration 6: Update the Note to Remove Attachment
Inside Apply to each (after successful SharePoint save):
Action: "Update a row" (Dataverse) Table name: Annotations Row ID: annotationid
Set these fields:
documentbody = null
filename = concat(items('Apply_to_each')?['filename'],
' (Moved to SharePoint)')
mimetype = null
isdocument = false
notetext = concat(
coalesce(items('Apply_to_each')?['notetext'], ''),
' Attachment moved to SharePoint.')What it does:
- Removes the file content: By setting documentbody to null (a static value for all notes), the note no longer takes up file storage. There is no need to reference the current value for this field—you always want it cleared.
- Appends to filename for clarity: The filename is appended with “Moved to SharePoint” to make the action obvious, even in list views.
- Clears MIME type and marks as not a document: Both mimetype and isdocument are set to fixed values (null and false, respectively) for every note, rather than pulling the current value from the loop, since your intent is simply to reset and indicate the attachment is gone.
- Appends a helpful message: The notetext is taken from the current note entry and you append “Attachment moved to SharePoint.” to notify users of the action while preserving any original comments on the note.
Limitations:
- The users are accustomed to seeing an attachment, so they might feel lost. The appended message is crucial to mitigate this.
- If you have automated processes that depend on isdocument = true, you may need to revise logic to account for migrated notes.
The Dedicated-Tool Path: CB Dynamics 365 Seamless Attachment Extractor
CB Dynamics 365 Seamless Attachment Extractor is a dedicated solution for Dynamics 365 admins who want to offload Dynamics 365 attachments without building or maintaining custom automation. You can store the offloaded attachments either in SharePoint, Azure Blob Storage, or Azure File Storage.
The service monitors all attachment-related activity in Dynamics 365 and automatically triggers extraction, moving files directly to your chosen storage with no flow logic to write or maintain. Where the Power Automate path requires a dedicated engineer and ongoing upkeep, this solution, although paid per user, is self-contained from day one and handles everything without additional maintenance effort.
CB Dynamics 365 Seamless Attachment Extractor also eliminates the process fragility that often plagues custom automation. If the engineer who built your flows leaves, moves on, or is simply unavailable, your attachment pipeline becomes an unowned dependency that nobody else can quickly resolve. A self-contained solution removes that single-person risk entirely.
From an end-user perspective, this solution replaces the physical file with a link pointing to the external storage location, so workflows, business processes, and access permissions remain unaffected.
An important point for this solution or any Power Automate solution you might build is ensuring that files do not leave your CRM and storage systems using any external service in between. This is particularly relevant for companies handling sensitive data or needing to maintain GDPR compliance, but it is also a general best practice.
This specific solution can compress and decompress files on the fly and encrypt and decrypt them using AES-256. Achieving comparable functionality in Power Automate would require building and maintaining custom connectors or external processes, which adds considerable complexity and overhead.
A 15-day free trial with full functionality is available, and the solution can be purchased through Microsoft Marketplace, which simplifies procurement for organizations already buying through Microsoft’s ecosystem.
Side-by-Side Comparison
| Criteria | Power Automate | CB Dynamics 365 Seamless Attachment Extractor |
| Cost | Depends on your licensing, potentially high maintenance cost (see note below) | Paid with a free trial available and fully predictable cost |
| Ongoing Maintenance | Requires monitoring, connector auth checks, flow fixes | Vendor-managed, including with new Dynamics 365 and storage versions |
| Time to Deploy | Long – Build, test, harden, document | Fast – deploy packaged setup Less than 30 minutes |
| Historical Migration | Requires separate bulk flow/project | Optional First Pass migration service |
| Storage Targets | Standard connectors; advanced targets need custom logic | SharePoint, Azure Blob, Azure File Storage |
| Reliability | Depends on flow design, quotas, retries | Purpose-built for attachment offloading |
| Security Features | Custom implementation required | AES-256 encryption and compression included |
| User Experience | Often needs custom link rendering/UI tweaks | Untouched – Replaces files with working links transparently |
| Internal Skill Dependency | High | Low |
NOTE:
Because Dynamics 365 Enterprise licenses already include rights to use the Dataverse connector and some request capacity, you might not need additional licenses if your flow is built, owned, and triggered strictly within your Dynamics 365 environment. If you do need extra licensing, you will typically require either Power Automate Premium (~$15/user/month) or a Power Automate Process plan (~$150/month per flow). There is no direct cost per API call, but daily request limits apply: about 40,000 requests per user and 250,000 per flow under the Process plan. High‑volume attachment extraction can make you hit these limits quickly.
Bottom line
If you have Power Platform engineering capacity and low-to-medium attachment volume, the DIY flow is a legitimate option for offloading Dynamics 365 attachments. In any case, make sure to build it properly from day one (idempotency, retry logic, a PCF link renderer). If you’re a lean IT team with no one who wants to own another pipeline, the managed tool removes a category of risk in exchange for a paid license. Analyze what makes sense for your project and leave your comment below if you have any questions.
Contact Connecting Software and prepare all your questions regarding Dynamics 365 attachment offloading (yes, even the technical ones!). You’ll leave your personalized demo with all you need to make an informed decision, namely what to expect regarding features, pricing, deployment, and support if you choose the dedicated tool.
The full article was originally posted on June 30, 2026, on the CRM Software Blog.
Connecting Software is proud to be one of CRM Software Blog’s top contributors since 2019.
The post Dynamics 365 Attachment Offloading: Power Automate vs. Dedicated Solution appeared first on CRM Software Blog | Dynamics 365.