Media: the part of a messaging system that fills the disk
Provider-hosted media expires. Copy what you need when it arrives, serve it with an authorised hand-off rather than by streaming bytes through your application, and get the file permissions right - which is the bug that leaks files or 403s your own users.
Copy on arrival
A webhook tells you a media message arrived and gives you an id. Fetch it then, not when somebody opens the conversation. By then it may be gone, and the customer's photograph of the damaged part was the whole evidence.
Do the fetch in a worker rather than in the webhook handler. It is slow, it can fail, and the handler's only job is to acknowledge.
Serving it without occupying a worker
The application decides whether this person may see this file. The web server or the object store moves the bytes.
# The app authorises, then hands off. nginx serves the file;
# the worker is free again immediately.
return Response(
headers={"X-Accel-Redirect": f"/protected/{media.path}"},
media_type=media.content_type,
)The trap here is file mode. Files written by a temporary-file helper are created 0600 and keep that mode when moved into place - so the application can read them and the web server, running as a different user, cannot. The symptom is a 403 on your own files, from your own server, for no visible reason.
Do not put the id in a guessable URL
A sequential id in a media URL is an enumeration attack on every customer's photographs. Use a random identifier, and authorise every request anyway - obscurity is not the control, it is the thing that makes the control's absence survivable for a while.
What to store
- The bytes, in object storage, not in the database.
- The content type the provider reported and the one you detected. They disagree more often than you would like.
- The original filename, for documents. It is what somebody searches their phone for later.
- A hash, so the same file arriving twice is stored once.
- Which conversation and message it belongs to, for deletion.
Deletion has to reach it
When a customer asks for their data to be deleted, the media is part of it. A deletion routine that clears rows and leaves object storage full of photographs has not deleted anything - see retention.
Questions people actually ask
Does WhatsApp media expire?
Yes. Media hosted by the platform is available for a limited period after the message. If a photograph matters to you, copy it when it arrives.
Should I proxy media through my application?
Not the bytes. Authorise the request in the application and hand off the actual transfer to the web server or object store, or every large download occupies an application worker.
Njiwa
One inbox for WhatsApp, Facebook and Instagram, and an API that sends over either WhatsApp rail. 7 days free, no card.