Object storage
Object storage for SaaS applications: isolate tenant data without shared secrets
SaaS applications often need to store uploads, exports and generated artifacts that do not belong in a relational database. S3-compatible storage can hold those objects efficiently, but the application must still enforce tenant authorization and lifecycle rules.
Keep tenant authorization in the application
Knowing an object key should not be sufficient to download another tenant’s file. The application should verify the authenticated user’s tenant and record ownership before issuing a read or presigned URL.
Random keys reduce guessing but do not replace authorization. Treat every object request as access to customer data.
Avoid one credential per browser user
Most SaaS users do not need permanent S3 credentials. The backend can use a scoped service identity and delegate individual uploads or downloads through short-lived signed URLs.
This keeps provider credential rotation independent from end-user account management and avoids distributing long-lived secrets to unmanaged devices.
Store object references transactionally
The database should record object ID, owning tenant, state and relevant metadata. Handle failure between database commit and object upload so orphaned objects or dangling database references can be reconciled.
Background cleanup should operate from explicit states and conservative age thresholds so one transient query cannot trigger broad deletion.
Design tenant deletion carefully
Account deletion may require deleting or retaining customer objects according to contractual and legal requirements. Versioning, Object Lock and lifecycle rules can affect when bytes are actually removable.
Record deletion requests and completion evidence without placing customer PII in bucket names or provider project descriptions unnecessarily.
Test cross-tenant negative cases
Integration tests should attempt to request another tenant’s object identifier, alter a presigned key and use expired URLs. All must fail at the appropriate authorization layer.
Storage isolation and application authorization should reinforce each other so a mistake in one layer does not automatically expose every tenant.