Object storage such as an S3-compatible blob store persists arbitrary binary files outside the relational database, while the database stores only metadata and a reference to the object.
In simpler words
Large files live in a blob store, not in Postgres rows. The database just remembers where a file is and what it is.
The judgment call is not how to call a storage SDK. It is why a file never belongs as a database BLOB column here.
Describe a presigned-upload flow versus a proxy-upload flow
Name authorization risks specific to file access
Pick validation rules for size, type, and ownership
Why blob storage, not a database column
Definition
A database BLOB column stores file bytes inline in table rows, whereas object storage stores those bytes in a separate, horizontally scalable service referenced by a key.
In simpler words
Postgres is good at rows and indexes. It is a poor and expensive place to keep large files.
Storing files in Postgres bloats backups, slows replication, and consumes connection-pool memory for something a blob store handles far more cheaply.
The entity keeps a storage key, original filename, mime type, size, and uploader. The bytes live in S3, or a local equivalent, under that key.
This follows the same own-the-smallest-correct-thing instinct behind choosing Redis or a state layer for the right slice of data. Postgres owns structured relations, not binary blobs.
The database never sees file bytes, only the pointer and metadata needed to authorize and display it.
Presigned URLs versus proxying through Nest
Definition
A presigned URL is a time-limited, credential-scoped link that lets a client upload or download directly against object storage without the API server handling the file bytes.
In simpler words
Let the browser talk to the file store directly with a temporary permission slip instead of routing every byte through Nest.
A presigned upload has Nest issue a short-lived URL scoped to one key, and the browser sends the file straight to storage. Nest never touches the large request body.
A proxy upload has the browser send the file to Nest, which streams it to storage. This is simpler to validate before it lands anywhere, but ties up Nest processes during the transfer.
Either way, authorization happens before the URL or stream is issued. Never trust a client-supplied storage key without checking that the requester owns the related record.
The presigned URL is generated only after Nest confirms the user may touch this ticket.
Validating what lands in storage
Definition
Upload validation constrains file size, mime type, and ownership before a file is accepted, since object storage will happily persist anything a client sends.
In simpler words
Check size, type, and permission before trusting an upload. The blob store will not do that for you.
Enforce a maximum size and an allow-list of mime types on the server. Never trust the browser-reported content type alone.
Reject uploads for records the user does not own, even when a presigned flow makes it tempting to skip that check on the client.
Treat untrusted file types carefully before rendering them inline. SVG and HTML uploads are classic vectors for injected scripts.
Keep in mind
Postgres stores the pointer; object storage stores the bytes, never the reverse.
Authorize before generating a URL, not after.
Validate size, type, and ownership on the server regardless of upload strategy.
Test
Check your understanding
At least 10 questions — mix of concept, syntax, practical, and logic. Score ≥ 80% (enforced by the API) to save progress.