The Problem: Storage Growth vs. Audit Trail Requirements

As Odoo instances mature, attachment storage consistently emerges as one of the quietest infrastructure challenges. Users naturally upload files across Sales, Accounting, Project, HR, and Chatter. Over time, the ir.attachment table and filestore can grow from gigabytes to hundreds of gigabytes, impacting backup windows, replication latency, and hosting costs.
 
Yet deleting attachments is rarely an option. Compliance frameworks, internal audit requirements, and operational backtracking demand that historical documents remain accessible and traceable. Teams often face a familiar tension: storage costs are climbing, but record integrity cannot be compromised.
 
This article outlines a structured, standard-first approach to managing Odoo attachments at scale. The goal is simple: preserve every record link and audit trail while transparently relocating binary storage to external systems like Microsoft SharePoint. No core overrides. No fragile workarounds. Just a clean architectural pattern that aligns with Odoo’s native design.

💡 The Core Principle: Keep the Link, Move the Blob

Understanding how Odoo stores files is essential to designing an effective strategy:
 
				
					ir.attachment (Database Record)
├── id, create_date, name, mimetype
├── res_model, res_id  → 🔗 Foreign keys linking to the source record
└── db_datas / store_fname → 📦 Pointer to the actual binary content
				
			
When a file is uploaded, Odoo creates:
  1. A metadata row in PostgreSQL (ir.attachment)
  2. A binary payload stored either in the database (db_datas) or on the server filesystem (store_fname / filestore)
 
The key insight for storage optimization: you do not need to delete the ir.attachment record to reclaim space. You only need to relocate where the binary payload lives. As long as res_model and res_id remain intact, the attachment continues to appear in chatter, the Documents app, and reporting views. When users click “Download,” Odoo resolves the binary from its new location transparently.
 
This principle—preserve metadata, relocate binaries—forms the foundation of every production-ready attachment strategy we design.

🛡️ Tier 1: Standard Odoo Features First

Before introducing external storage, it’s important to verify that Odoo’s built-in capabilities are properly configured. In many growing instances, simple adjustments here recover noticeable space and improve system stability.
 

Filestore Configuration

Modern Odoo versions default to filesystem storage, but legacy or migrated databases sometimes retain ir_attachment.location = db. Storing binaries in PostgreSQL inflates database size, slows backups, and complicates point-in-time recovery. Verifying that attachments use the OS filestore is a foundational step.
 

Garbage Collection & Orphaned Files

When records are deleted or archived, Odoo’s scheduled action ir.attachment: garbage collector cleans up attachments that no longer reference a valid record. Ensuring this cron is active, properly scheduled, and periodically reviewed prevents silent accumulation of orphaned binaries.
 

Infrastructure-Level Upload Controls

Odoo does not enforce attachment size limits at the application layer. Configuring client_max_body_size (Nginx) or LimitRequestBody (Apache) at the reverse proxy level prevents oversized uploads (e.g., uncompressed archives, raw video files) from entering the system in the first place.
 

Functional Discipline & Duplicate Prevention

Teams often upload the same contract or invoice to multiple records. Encouraging the use of Odoo’s Documents App as a central repository, then linking existing attachments in chatter, reduces redundant storage. Additionally, standardizing image formats (WebP, optimized JPEGs) ensures original uploads don’t consume unnecessary disk space, especially since Odoo auto-generates thumbnail variants regardless.
 
These steps require no additional modules and are typically addressed during routine system health checks. They establish a clean baseline before considering external storage routing.

☁️ Tier 2: Transparent External Storage with SharePoint

Once standard configurations are verified, the next logical step is offloading binary storage to an enterprise-grade external system. For organizations already using Microsoft 365, SharePoint is a natural fit. The challenge has always been maintaining Odoo’s native workflows while moving binaries off-server.
 
This is where the Odoo Community Association (OCA) storage ecosystem provides a production-ready path.
 

Why This Aligns with Odoo’s Architecture

The OCA fs_storage modules follow Odoo’s official inheritance patterns. They do not override core attachment logic with custom Python; instead, they hook into ir.attachment read/write methods using fsspec routing. The result is:
  • Configuration-driven storage routing via Odoo’s standard UI
  • Zero modification to ir.attachment core behavior
  • Full compatibility with Odoo’s ORM, REST API, Studio, and standard apps
  • Unchanged user experience: chatter, Documents, and reporting continue working natively
 

📦 The OCA Module Stack

Module
Purpose
fs_storage
Base framework for fsspec-compatible backends (S3, Azure, SharePoint, SFTP, etc.)
fs_attachment
Intercepts attachment I/O and routes binaries to the configured storage backend
microsoft_drive_account
Handles OAuth 2.0 authentication flow with Microsoft Graph API
fs_storage_ms_drive
SharePoint/OneDrive connector for transparent binary offloading
📌 Version Note: This stack is stable and production-tested for Odoo 16.0, 17.0, and 18.0. Odoo 14/15 relied on the legacy storage_backend API, which lacked transparent routing and required manual synchronization jobs. For teams still on 15 or below, upgrading to 16+ is the recommended prerequisite before implementing external storage routing.
 

🔄 How the Integration Works (Architecture Overview)

  1. Upload Interception: When a file is uploaded to any Odoo model, fs_attachment evaluates the attachment against configured routing rules.
  2. Routing Decision: Based on criteria like file size, record model, or creation date, Odoo determines whether the binary stays local or routes to SharePoint.
  3. Transparent Storage: If routed externally, the binary uploads via Microsoft Graph API. The ir.attachment record updates its storage reference, but res_model, res_id, and metadata remain untouched in PostgreSQL.
  4. Seamless Retrieval: When users access the attachment, Odoo resolves the binary from SharePoint automatically. No workflow changes, no custom download buttons, no broken links.
 

Implementation Considerations

Area
Typical Consideration
Authentication
Microsoft Entra ID (Azure AD) with delegated OAuth 2.0 permissions (Files.ReadWrite.All). Token refresh and service account scoping require careful planning.
Folder Organization
Structuring SharePoint libraries by model and period (e.g., /OdooAttachments/sale.order/2024/06/) simplifies auditing, compliance reporting, and manual verification.
Hybrid Routing
Keeping small or frequently accessed files local (<5MB) while routing large or cold attachments to SharePoint balances performance, cost, and user experience.
Migration Execution
Historical attachments are best migrated in controlled batches using OCA’s built-in tools. This respects Microsoft Graph API rate limits and allows rollback if needed.
Compliance Alignment
SharePoint retention labels, versioning, and eDiscovery can complement Odoo’s audit trail. Defining the “source of truth” for legal holds upfront avoids ambiguity.
While the modules themselves are straightforward, the architecture around routing rules, authentication scoping, migration sequencing, and compliance mapping is where implementation expertise adds measurable value.

📊 Strategy Summary

Tier
Approach
Tooling
Best Suited For
1
Verify filestore, enable GC, enforce proxy limits, standardize upload habits
Odoo core (all supported versions)
Quick stabilization, immediate space recovery
2
Offload large/cold attachments to SharePoint
OCA fs_storage_ms_drive (Odoo 16.0+)
Organizations on Microsoft 365 seeking scalable, compliant storage
3
Hybrid routing + automated archival flags
OCA modules + Odoo Automated Actions
High-volume models requiring performance/cost balance
4
Retention policies + compliance mapping
Odoo Documents app + SharePoint retention labels
Regulated industries (finance, healthcare, legal, manufacturing)

🎯 Implementation Philosophy: Plan First, Execute Carefully

Storage optimization is rarely a “flip a switch” task. In production environments, we typically follow this sequence:
  1. Audit the footprint: Analyze attachment distribution by model, size, and age to identify routing candidates.
  2. Validate Tier 1: Confirm filestore usage, GC cron health, and proxy limits are properly configured.
  3. Pilot external routing: Test SharePoint integration on a single model with a controlled batch before expanding scope.
  4. Design routing & migration rules: Align file size thresholds, model-based routing, and historical migration sequencing with business priorities.
  5. Document retention & compliance: Map Odoo metadata retention to SharePoint lifecycle policies to ensure audit readiness.
 
The tools are standard. The modules are well-maintained. The difference lies in how the architecture is planned, tested, and aligned with your organization’s compliance and operational requirements.

✅ Closing Thoughts

Attachment storage growth doesn’t require deleting history, rewriting core logic, or disrupting user workflows. By exhausting Odoo’s standard capabilities first and then transparently routing binaries to external storage like SharePoint, teams can reclaim infrastructure capacity while preserving every record link and audit trail.
 
If you’re evaluating storage optimization for your Odoo instance—whether you need an attachment footprint audit, routing rule design, OAuth scoping guidance, or a risk-managed migration plan—feel free to reach out. We’re happy to walk through your current architecture and help design a clean, compliant, and scalable approach.
DSCSA checklist form

Get Your DSCSA Readiness Checklist

Enter your name and email below — we’ll send the checklist PDF directly to your inbox.