skip to content

In Livewire, where does an uploaded file live before your action stores it, and what do the temporary_file_upload config defaults control?

level: middleimportance: must knowfreq 34%

answer

  1. livewire-tmp on the default disk
  2. global rules: required, file, max 12288 KB
  3. throttle:60,1 on the upload route
  4. signed URL valid 5 minutes
  5. files older than 24 hours pruned

basics

~20 s

Livewire keeps uploads in a livewire-tmp directory on the default filesystem disk until you store them; config/livewire.php's temporary_file_upload block sets that disk and directory, global rules (12 MB), the upload route's middleware, the signed-URL lifetime and cleanup.

solid answer

~40 s

Until an action calls `store()`, an upload is a file in `livewire-tmp/` on the filesystem's default disk, plus a small JSON metadata file. The `temporary_file_upload` block in `config/livewire.php` controls this: `disk` (from `LIVEWIRE_TEMPORARY_FILE_UPLOAD_DISK`, falling back to the default disk), `directory` (default `livewire-tmp`), `rules` applied at the upload endpoint (default `required`, `file`, `max:12288`, about 12 MB), `middleware` on the upload route (default `throttle:60,1`, with `web` always prepended), `max_upload_time` (5 minutes, the signed URL's lifetime), `preview_mimes`, and `cleanup` (true). Cleanup deletes temporary files older than 24 hours, but only on a local-style disk and only when a later upload finishes. `store()` copies the file, so the temporary copy stays until that cleanup.

go deeper

for a junior

Recall that uploads first land in livewire-tmp and that store() puts them somewhere permanent.

for a middle

Explain each temporary_file_upload key, the 12 MB global rule and the 24-hour cleanup triggered by later uploads.

for a senior

Design for multiple servers, sensitive files lingering after store(), and upload limits that must agree across PHP, web server and Livewire.

for a principal

Set retention and storage rules for user uploads that satisfy privacy expectations without adding operational burden.

## The temporary stage When a user selects a file on a **Livewire** file input, the file is uploaded before any component action runs. Livewire has to put it somewhere, and it cannot be the final location because the user has not submitted the form yet and your validation has not run. So it lands in a **temporary directory**, and the component property holds a `TemporaryUploadedFile` pointing at it. Your action later copies it to its permanent home with `store()` or `storeAs()`. ## The config block All of this is controlled by `temporary_file_upload` in `config/livewire.php` (publish it with `php artisan livewire:config`). | Key | Shipped value | Effective default | Controls | |---|---|---|---| | `disk` | `env('LIVEWIRE_TEMPORARY_FILE_UPLOAD_DISK')` | the app's default disk | where temporary files are written | | `directory` | `null` | `livewire-tmp` | directory on that disk | | `rules` | `null` | `required`, `file`, `max:12288` | validation at the upload endpoint | | `middleware` | `null` | `throttle:60,1` | middleware on the upload route (`web` is always prepended) | | `max_upload_time` | `5` | 5 minutes | lifetime of the signed upload URL | | `preview_mimes` | image, audio and video extensions | same | what `temporaryUrl()` may preview | | `cleanup` | `true` | true | prune temporary files older than 24 hours | Two things to notice. First, the **global rules** run at the upload endpoint for every file, before your component sees it; a receipt over 12 MB is rejected there and the error is reported on the bound property. Raising the limit means changing `rules` here **and** PHP's `upload_max_filesize` / `post_max_size` and any web-server body limit. Second, the upload route is protected by a **signed URL** that expires after `max_upload_time` minutes, so a very slow upload of a large file can fail once the signature expires. ## Cleanup is lazy Livewire does not schedule anything. When an upload finishes and `cleanup` is true, it scans the temporary directory and deletes files last modified more than a day ago. Consequences: - On a quiet app, stale files can linger until the next upload. - The scan runs inside the request that finishes an upload, so a huge directory makes that request slower. - On an S3 temporary disk this scan is skipped; you configure a bucket lifecycle rule instead. ## store() copies, it does not move `TemporaryUploadedFile::storeAs()` reads the temporary file as a stream and writes it to the target disk. The temporary file stays in `livewire-tmp` until cleanup removes it. That is harmless for correctness but matters for disk usage and privacy: sensitive receipts sit in the temporary directory for up to a day after being stored. If that matters, delete the temporary file after storing, which `TemporaryUploadedFile` supports with `delete()`. ## Operational checklist for an expense app 1. Set `rules` to what any upload may be (for example PDF or image, 10 MB), and keep the stricter per-field rules in the component. 2. Tighten `middleware`, such as a lower throttle for a public form. 3. Make sure the temporary disk is shared by every app server, or uploads land on one server and the save request reads from another. 4. Keep `cleanup` on, or replace it with your own scheduled pruning. 5. Watch `max_upload_time` if users upload large scans on slow connections. ## Why interviewers ask this Most Livewire upload bugs seen in production come from this temporary stage rather than from `store()`: files rejected by a global limit nobody remembered, saves failing on a second server, disks filling with day-old uploads, or private documents left readable in a temporary folder. A candidate who can name the config keys and explain the lazy cleanup has usually operated an upload feature, not just built one.

  • Your app runs on three web servers with local disks, and saves fail with missing temporary files. Why?
    The file was uploaded to `livewire-tmp` on one server's local disk, and the save request landed on another server that cannot see it. Point the temporary disk at shared storage, such as a shared volume or S3, so every server reads the same `livewire-tmp`.
  • A user's 20 MB scan is rejected even though the component validates max:25600. Why?
    Livewire's upload endpoint applies the global `temporary_file_upload.rules` first, and the default includes `max:12288`, about 12 MB. The file never reaches the component's rules. Raise the global rule, and PHP's and the web server's upload limits, to allow it.

saying these in an interview costs you the question

  • Believes store() moves the temporary file and removes it from livewire-tmp.
  • Thinks the component's own rules are the only validation a file passes.
  • Assumes Livewire schedules a cron job to clear livewire-tmp.
  • Uses a per-server local temporary disk behind a load balancer.
  • Expects the upload URL to stay valid indefinitely.