Short answer: for most SaaS document uploads, put the bytes in object storage and keep searchable metadata in Postgres or MySQL. That split is usually cheaper to scale and gives the application a smaller, faster database; it also keeps the audit trail explicit instead of hiding a file inside a row.
The scenario here is a media service processing receipts and retaining the original upload for audit. Large-file throughput is the deciding constraint. A receipt may be small today, but a scanned contract or a high-resolution invoice can turn a comfortable database design into a backup and replication problem.
Start with the audit record, not the bucket
Treat the database row as the source of truth for document state. Store owner ID, filename, MIME type, processing status, checksum, search fields, and the object key there. Store the binary separately. A listing API that only scans by prefix cannot answer “show this user’s PDFs from last month” without that document table.
There are two write boundaries.…