Question presented to candidate: "Users need to upload an avatar (a few hundred KB) and, elsewhere, video files of up to 50 MB. How would you handle file uploads in a Next.js App Router app, and when would you use a Server Action versus a Route Handler?"
What a strong answer should cover:
- A
<form>with<input type="file" name="file">posting to a Server Action: the action receivesFormData,formData.get("file")is aFile, and the form works with progressive enhancement. - Server Action bodies are limited to 1 MB by default (
experimental.serverActions.bodySizeLimit), and the limit includes multipart overhead; over it the action fails with "Body exceeded 1 MB limit". - Route Handlers have no such built-in limit:
await request.formData()for small files, or streamrequest.bodyto storage for large ones so the whole file is never held in memory. - Validation on the server: type allow-list, size limit, generated file names (never trust
file.namefor a path), authorization inside the action or handler. - For large or many files, prefer direct-to-storage uploads (presigned URLs) so the bytes do not pass through the Next.js server at all.
Clarifying questions expected:
- "Where do files end up: local disk, S3-compatible storage, a CDN?" β local disk does not work on serverless or across instances.
- "How large, and do users need progress bars or resumable uploads?" β decides form + action vs direct-to-storage.
Code / implementation expected: Yes β a Server Action upload with useActionState, a request.formData() Route Handler, and a streaming Route Handler.