Next.js Application File Storage
Store Files From Server Actions and Route Handlers — Without the Ephemeral Filesystem Trap
Serverless file storage for Next.js with global CDN delivery. Perfect for modern web apps.
Every Next.js app eventually learns the hard way that the runtime filesystem is ephemeral — write a file to disk in an API route on Vercel or any container host and it's gone on the next cold start or deploy. The fix is external storage, and files.link plugs into Next.js exactly where uploads naturally land: Server Actions, Route Handlers, and API routes. The cleanest modern pattern is a Server Action.
The form posts FormData, the action reads the File, converts it to a buffer, and runs the three-call upload server-side — POST /v1/files/{folderId} for a presigned URL and id, PUT the buffer, then POST /v1/files/confirm-upload with { ids: [id] } — using your raw API key from an environment variable that, because it's a Server Action, is never shipped to the client.
Roughly: 'use server'; export async function upload(formData) { const file = formData.get('file'); const buf = Buffer.from(await file.arrayBuffer()); const init = await fetch(\${API}/v1/files/${folderId}\, { method: 'POST', headers: { Authorization: process.env.FILESLINK_KEY, 'Content-Type': 'application/json' }, body: JSON.stringify({ files: [{ name: file.name }] }) }); const { urls } = await init.json(); await fetch(urls[0].url, { method: 'PUT', body: buf }); await fetch(\${API}/v1/files/confirm-upload\, { method: 'POST', headers: { Authorization: process.env.FILESLINK_KEY, 'Content-Type': 'application/json' }, body: JSON.stringify({ ids: [urls[0].id] }) }); return urls[0].url; } The identical three calls work from a Route Handler (app/api/upload/route.js) and from a Pages Router API route.
The returned URL drops straight into next/image as the src; files.link serves the image from a global CDN, though it does not do server-side transforms, so use next/image's own resizing/optimization on top for responsive variants. The deliberate contrast with Vercel Blob is portability: Blob is great until you self-host or move off Vercel, at which point you're rewriting your storage layer — files.link runs the same against Vercel, a Node container, AWS, or bare metal, with no platform coupling.
Against Uploadthing you avoid adopting a typed wrapper library and its hosting; against the AWS SDK you skip IAM and bucket setup entirely. Private files (user uploads, gated documents) are stored privately and served through expiring signed URLs your server mints after an auth check. Billing is prepaid credits, not per-request metering, so traffic spikes from a viral page don't translate into a surprise invoice line. Pair with the React and Node.js guides below for full-stack coverage.
Benefits With No Complexity
Global CDN delivery
Edge-cached worldwide
Signed-URL security
What You Get
Unlimited files
Unlimited storage
Public + Private storage
CDN ready links
Prepaid credits
More coming soon
How files.link Works
1. Upload
2. Copy
3. Use Anywhere
Why Developers Choose files.link
A Better Way to Store & Deliver Files
| Vercel Blob | Uploadthing | AWS S3 (aws-sdk) | files.link | |
|---|---|---|---|---|
| Works on Vercel and self-hosted equally | ||||
| No platform lock-in | ||||
| Global CDN (no Blob region limits) | ||||
| Key stays server-side in Server Actions | ||||
| Private files via signed URLs | ||||
| Prepaid credits (no per-request metering) |
Calculate Your Needs
Storage
Egress
CDN Bandwidth
Start Storing Files in Next.js
- Global CDN delivery
- Edge-cached worldwide
- Signed-URL security
- Unlimited files
- Unlimited storage
- Public + Private storage
- No subscription — prepaid credits keep spend predictable