Expiry and deletion
Every transfer has a retention period: 14 days by default, 1 to 90 days, or no expiry at all. It is the central promise of the app, so it is enforced twice.
Enforced in two places
At request time. The download routes refuse an expired transfer the moment it lapses. The promise made to the sender is exact and does not depend on when a scheduled task happens to run.
By the sweep. A task runs every 15 minutes and deletes the files from disk and the rows from the database. This is the part that makes "the files are deleted from the server" literally true rather than merely "the files are unreachable".
Order matters in that sweep: files first, then rows. A crash halfway through leaves rows pointing at missing files, which the download handler already treats as gone — whereas deleting the rows first would leave files on disk that nothing references and nothing will ever clean up.
The same task also removes abandoned drafts, expired sessions, used-up tokens, and storage directories with no matching row.
The scheduled task needs a long-lived process
The sweep runs on a timer inside the Node process. The app is meant to run as
node .output/server/index.mjs behind a proxy, or as the Docker image, and on
either it works unattended.
On a platform that starts a process per request, expiry would still be refused at download time — but nothing would ever reclaim the disk.
The warning before deletion
Shortly before a transfer lapses, its sender gets one e-mail: the files are about to be deleted, here is the link, and here is how many times it has been downloaded so far. "Not downloaded yet" the day before deletion is the case worth acting on.
The lead time is NUXT_EXPIRY_WARNING_HOURS — 24 by default, 0 to switch it
off.
It goes to the sender rather than the recipients for two reasons. The sender is the one who can act on it — download the files again, or re-send. And warning recipients would turn one expiry into as many extra outbound mails as the transfer has addresses.
A transfer whose whole retention is shorter than the lead time is skipped. A warning that arrives with the transfer itself is noise.
Unlimited retention
Choosing "no expiry" stores a NULL expiry rather than a far-future date, and
the sweep skips those rows entirely. A sentinel date would eventually arrive.
Use it sparingly. The disk is yours, and a tool whose whole point is that files go away works best when they mostly do.