# Next.js File Upload Size Limit: Server Actions and Route Handlers Guide

Next.js file upload size limits depend on whether you use Server Actions or Route Handlers. Server Actions enforce a strict default request body limit of `1MB`, while Route Handlers stream requests but face host platform boundaries like Vercel's `4.5MB` serverless payload ceiling. While next.config.js adjusts Server Action limits, multi-megabyte workflows require direct-to-storage uploads or external indexed workspaces.

Source: https://fast.io/resources/nextjs-file-upload-size-limit/
Author: [Derek Labian](https://fast.io/authors/derek-labian/)
Last reviewed: 2026-10-26

## What Is the Default Next.js File Upload Size Limit in Server Actions and Route Handlers?

Next.js Server Actions enforce a strict default request body size limit of `1MB`, while serverless hosting platforms like Vercel cap total function request payloads at `4.5MB`. Crossing either boundary triggers an immediate HTTP 413 Payload Too Large error before your application logic can inspect or process the incoming bytes.

The Next.js file upload size limit is the maximum request payload size enforced by Next.js Server Actions (default 1MB) and route handlers, designed to prevent memory overload in serverless functions. Understanding where this limit originates is critical for building reliable file intake pipelines in modern React applications.

In the Next.js App Router, file uploads follow one of two execution paths: Server Actions or Route Handlers. Each path handles request bodies through completely different runtime mechanics:

1. **Server Actions:** When a client invokes a Server Action using `multipart/form-data` or serialized arguments, Next.js buffers and parses the incoming HTTP request body before passing the parsed data to your server function. To protect Node.js runtimes and serverless instances from memory exhaustion and denial-of-service attacks, Next.js sets a hard default limit of `1MB` on this incoming payload, as documented in the official [Next.js Server Actions documentation](https://nextjs.org/docs/app/api-reference/config/next-config-js/serverActions). If an uploaded file pushes the request body over `1MB`, Next.js terminates the request and throws an error before the function body executes.

2. **Route Handlers:** Route Handlers (`app/api/upload/route.ts`) replace legacy Pages Router API routes. Unlike Server Actions, Route Handlers do not impose an arbitrary `1MB` parsing ceiling in Next.js core. Instead, they expose the standard Web API `Request` object directly to your code. While a self-hosted Node.js instance running Next.js can stream files through Route Handlers without a built-in framework ceiling, managed serverless platforms impose their own hard infrastructure boundaries. According to the [Vercel Function limitations](https://vercel.com/docs/functions/limitations), every serverless function invocation is restricted to a maximum request and response payload limit of `4.5MB`.

Many developers upgrading from the Pages Router search for the legacy `export const config = { api: { bodyParser: false } }` directive. That configuration option only applied to `pages/api` routes and is completely ignored by the App Router. In the App Router, payload boundaries are governed by `next.config.js` for Server Actions, and by the underlying server or hosting environment for Route Handlers.

The following comparison table breaks down default payload limits, configurable maximums, and failure behaviors across Next.js runtimes and cloud hosting providers:

| Runtime or Hosting Layer | Default Body Limit | Maximum Configurable Limit | Configuration Location | Failure Status Code |
|---|---|---|---|---|
| Next.js Server Actions (App Router) | 1MB | Custom (e.g., 10MB) | serverActions.bodySizeLimit in next.config.js | 413 Body exceeded limit |
| Next.js Route Handlers (Self-Hosted Node.js) | No framework limit | Operating system and proxy limit | Reverse proxy (e.g., Nginx client_max_body_size) | 413 Payload Too Large |
| Vercel Serverless Functions | 4.5MB | 4.5MB (Hard platform limit) | Non-configurable on Vercel platform | 413 FUNCTION_PAYLOAD_TOO_LARGE |
| AWS Lambda (HTTP API Gateway) | 10MB | 10MB (Hard AWS quota) | AWS API Gateway payload configuration | 413 Request Entity Too Large |
| Cloudflare Workers | 100MB (Standard) | 500MB (Enterprise) | Cloudflare Dashboard or wrangler.toml | 413 Request Entity Too Large |
| Fast.io Intelligent Workspaces | 25 GB (Starter) / 50 GB (Business) / 100 GB (Enterprise) | Plan storage allocation | Workspace configuration and MCP access | Handled via chunked transfers |

When diagnosing upload failures, identifying the exact boundary that rejected the payload saves hours of debugging. If the failure occurs during a Server Action invocation, the `1MB` Next.js internal buffer is almost always the cause. If the error occurs on an endpoint deployed to Vercel with files exceeding `4.5MB`, the platform serverless proxy is rejecting the connection before Next.js ever sees it.

## How to Configure Server Actions bodySizeLimit in next.config.js

To allow files larger than `1MB` through Server Actions, you must explicitly raise the body size ceiling in your configuration file. Next.js exposes the `bodySizeLimit` property within the `serverActions` configuration object.

### Configuration Syntax Across Next.js Versions

Depending on the exact version of Next.js running in your repository, the configuration key sits either directly under `serverActions` or inside the `experimental` block:

In modern Next.js releases where Server Actions are fully stable, configure `serverActions.bodySizeLimit` in your `next.config.js` or `next.config.ts`:

```javascript
// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  serverActions: {
    bodySizeLimit: '10mb',
  },
};
module.exports = nextConfig;
```

If your project uses TypeScript for configuration, define the setting inside `next.config.ts`:

```typescript
// next.config.ts
import type { NextConfig } from 'next';
const nextConfig: NextConfig = {
  serverActions: {
    bodySizeLimit: '10mb',
  },
};
export default nextConfig;
```

In earlier Next.js 14 versions where the property was first introduced, the setting was nested under `experimental.serverActions`:

```javascript
// next.config.js (Legacy 14.x syntax)
/** @type {import('next').NextConfig} */
const nextConfig = {
  experimental: {
    serverActions: {
      bodySizeLimit: '10mb',
    },
  },
};
module.exports = nextConfig;
```

The `bodySizeLimit` property accepts either a raw integer representing the number of bytes (such as `10485760` for `10MB`) or a string format supported by the `bytes` library (such as `'500kb'`, `'2mb'`, or `'10mb'`).

### The Multipart Form Overhead Trap

A common trap when configuring `bodySizeLimit` is setting the threshold to the exact size of the expected file. For example, if your application permits users to upload images up to `2MB`, configuring `bodySizeLimit: '2mb'` will cause legitimate `2MB` uploads to fail.

The `bodySizeLimit` directive governs the raw HTTP request body, not just the file payload. When a web browser submits an upload using `multipart/form-data`, it packages the file alongside boundary delimiters, HTTP part headers (`Content-Disposition`, `Content-Type`), and any companion form fields. This packaging adds between `10KB` and `50KB` of protocol overhead to the transmission.

If a user uploads a file that measures exactly `2MB`, the total transmitted body will be slightly larger. Because the raw payload exceeds the `2MB` ceiling, Next.js aborts the request with a `413 (Body exceeded 2 MB limit)` error. Always allocate at least `100KB` of headroom in your `bodySizeLimit` configuration above your user-facing file size restriction.

### Server Action Implementation Example

The following example demonstrates how to implement a Server Action that accepts an uploaded file via standard `FormData`, validates file properties, and safely processes the buffer:

```typescript
// app/actions/upload.ts
'use server';

interface UploadResult {
  success: boolean;
  fileName?: string;
  size?: number;
  error?: string;
}

const MAX_ALLOWED_FILE_BYTES = 8 * 1024 * 1024; // 8MB limit for application logic
const ALLOWED_MIME_TYPES = ['image/jpeg', 'image/png', 'application/pdf'];

export async function uploadDocumentAction(formData: FormData): Promise<UploadResult> {
  try {
    const file = formData.get('document') as File | null;
    if (!file || file.size === 0) {
      return { success: false, error: 'No file provided in form submission.' };
    }
    if (file.size > MAX_ALLOWED_FILE_BYTES) {
      return {
        success: false,
        error: 'File exceeds maximum permitted size of 8MB.',
      };
    }
    if (!ALLOWED_MIME_TYPES.includes(file.type)) {
      return {
        success: false,
        error: 'Unsupported file format. Only JPEG, PNG, and PDF files are allowed.',
      };
    }
    // Convert the Web File to an ArrayBuffer or Buffer for processing
    const arrayBuffer = await file.arrayBuffer();
    const buffer = Buffer.from(arrayBuffer);
    console.log(`Successfully ingested ${file.name} (${buffer.length} bytes)`);
    return {
      success: true,
      fileName: file.name,
      size: file.size,
    };
  } catch (error) {
    console.error('Server Action upload failed:', error);
    return {
      success: false,
      error: 'Server encountered an error while processing the uploaded file.',
    };
  }
}
```

While raising `bodySizeLimit` in `next.config.js` resolves upload errors for small and medium files on traditional servers, it cannot override infrastructure caps imposed by serverless hosting providers.

## How to Handle Large Uploads in App Router Route Handlers

When you need fine-grained control over HTTP headers, streaming ingestion, or integration with external services, App Router Route Handlers (`app/api/.../route.ts`) provide a flexible alternative to Server Actions.

### Building a Route Handler with Request Parsing

Route Handlers evaluate HTTP methods through exported functions such as `POST`, `PUT`, or `PATCH`. Because Next.js does not apply the `1MB` Server Action ceiling to Route Handlers, your endpoint can accept larger payloads out of the box on self-hosted infrastructure.

The following implementation shows an App Router Route Handler processing a multipart file upload using native Web standard APIs:

```typescript
// app/api/upload/route.ts
import { NextResponse } from 'next/server';

export const dynamic = 'force-dynamic';

export async function POST(request: Request) {
  try {
    // Verify content type is multipart/form-data
    const contentType = request.headers.get('content-type') || '';
    if (!contentType.includes('multipart/form-data')) {
      return NextResponse.json(
        { error: 'Invalid content type. Expected multipart/form-data.' },
        { status: 400 },
      );
    }
    // Parse the incoming multipart form data
    const formData = await request.formData();
    const file = formData.get('file') as File | null;
    if (!file) {
      return NextResponse.json(
        { error: 'No file found in request payload.' },
        { status: 400 },
      );
    }
    const arrayBuffer = await file.arrayBuffer();
    const buffer = Buffer.from(arrayBuffer);
    return NextResponse.json({
      success: true,
      fileName: file.name,
      fileSize: file.size,
      mimeType: file.type,
    });
  } catch (error) {
    console.error('Route Handler upload error:', error);
    return NextResponse.json(
      { error: 'Failed to process file upload.' },
      { status: 500 },
    );
  }
}
```

### Memory Consumption and Node.js Buffer Bottlenecks

While `await request.formData()` and `await file.arrayBuffer()` are simple to write, both methods buffer the entire file into server memory. In serverless environments where memory allocations range from `512MB` to `1024MB`, buffering concurrent multi-megabyte files can trigger Node.js Out-of-Memory (OOM) fatal errors.

To process larger files efficiently on dedicated Node.js servers, read the incoming payload as a stream via `request.body`. Streaming chunks directly to disk or an object storage bucket prevents memory spikes:

```typescript
// app/api/stream-upload/route.ts
import { NextResponse } from 'next/server';
import { createWriteStream } from 'fs';
import { pipeline } from 'stream/promises';
import { Readable } from 'stream';

export async function POST(request: Request) {
  if (!request.body) {
    return NextResponse.json({ error: 'Request body is empty.' }, { status: 400 });
  }
  // Convert Web ReadableStream to Node.js Readable stream
  const nodeReadable = Readable.fromWeb(request.body as import('stream/web').ReadableStream);
  const destinationPath = '/tmp/incoming-upload.bin';
  const fileWriteStream = createWriteStream(destinationPath);
  // Stream bytes directly to disk without buffering the full file in RAM
  await pipeline(nodeReadable, fileWriteStream);
  return NextResponse.json({ success: true, message: 'File streamed successfully.' });
}
```

### The Hosting Provider Ceiling: Vercel Platform Payload Caps

Even though Route Handlers avoid the Next.js `1MB` Server Action parser limit, deploying to Vercel places your code behind an immutable edge proxy. Vercel serverless functions enforce a strict `4.5MB` payload cap on all incoming requests and outgoing responses.

If a client transmits a file exceeding `4.5MB` to your Route Handler hosted on Vercel, the platform proxy rejects the transmission before the serverless container spins up. The client receives an HTTP 413 error carrying the error code `FUNCTION_PAYLOAD_TOO_LARGE`. No adjustment in `next.config.js` or Route Handler code can increase this `4.5MB` threshold on Vercel infrastructure.

### Serverless Execution Timeouts: HTTP 504 Gateway Timeouts

In addition to payload volume caps, serverless functions operate under strict execution duration limits. On Vercel, serverless functions enforce strict execution duration limits, defaulting to short execution windows on standard tiers.

When users upload files over slow or congested cellular connections, transmitting even a `3MB` or `4MB` payload can take tens of seconds. In this scenario, the request does not fail with an HTTP 413 error. Instead, the proxy terminates the connection when the execution timer expires, returning an HTTP 504 Gateway Timeout.

For production web applications requiring uploads larger than a few megabytes, routing raw file bytes through Next.js server instances is the wrong architectural design.

## Why Serverless Architecture Requires Direct-to-Storage Uploads

The production standard for handling large files in Next.js is the Direct-to-Storage pattern. Instead of routing binary file data through Server Actions or Route Handlers, the browser transmits the file directly to cloud object storage using presigned upload URLs.

In this architecture, your Next.js application acts as an authentication and orchestration gatekeeper rather than a file transfer proxy.

### How the Presigned URL Flow Operates

The direct-to-storage architecture separates metadata coordination from binary data transport across four distinct steps:

1. **Request Upload Signature:** The client initiates an upload by sending lightweight JSON metadata (such as filename, file size, and MIME type) to a Next.js Server Action or Route Handler.
2. **Generate Presigned URL:** The Next.js backend verifies user permissions, validates file constraints against business rules, and calls the storage provider API to generate a temporary presigned PUT URL.
3. **Direct Browser Upload:** The browser receives the presigned URL and uploads the raw file directly to the cloud storage bucket using a standard HTTP PUT request. Because data flows directly from the client to object storage, the payload never touches your Next.js serverless function.
4. **Confirm Upload Completion:** Once the direct upload finishes, the client notifies the Next.js backend with the file identifier. Next.js creates database records or initiates downstream background processing.

### Implementation: Generating Presigned Upload URLs

The following Route Handler demonstrates how to validate an incoming file upload request and return a short-lived presigned upload URL:

```typescript
// app/api/upload/presigned/route.ts
import { NextResponse } from 'next/server';

interface PresignedRequest {
  fileName: string;
  fileType: string;
  fileSize: number;
}

export async function POST(request: Request) {
  try {
    const body: PresignedRequest = await request.json();
    const { fileName, fileType, fileSize } = body;
    // 1. Enforce business validation rules
    if (fileSize > 500 * 1024 * 1024) { // 500MB application ceiling
      return NextResponse.json(
        { error: 'File exceeds maximum allowable limit of 500MB.' },
        { status: 400 },
      );
    }
    // 2. Generate a unique storage key
    const fileId = crypto.randomUUID();
    const storageKey = `uploads/${fileId}-${fileName}`;
    // 3. Request a signed PUT URL from your storage provider API or S3 client
    const uploadUrl = `https://storage.example.com/${storageKey}?signature=token_mock`;
    return NextResponse.json({
      success: true,
      uploadUrl,
      fileId,
      storageKey,
    });
  } catch (error) {
    console.error('Presigned URL generation error:', error);
    return NextResponse.json(
      { error: 'Could not generate upload signature.' },
      { status: 500 },
    );
  }
}
```

### React Client Component for Direct Uploads

On the frontend, a React client component captures the selected file, requests the presigned URL, and streams the binary payload directly to storage using `fetch` with progress tracking:

```tsx
// app/components/DirectUploader.tsx
'use client';

import { useState } from 'react';

export function DirectUploader() {
  const [uploading, setUploading] = useState(false);
  const [status, setStatus] = useState<string>('');
  async function handleFileSelection(e: React.ChangeEvent<HTMLInputElement>) {
    const file = e.target.files?.[0];
    if (!file) return;
    setUploading(true);
    setStatus('Requesting secure upload authorization...');
    try {
      // Step 1: Request presigned URL from Next.js Route Handler
      const authResponse = await fetch('/api/upload/presigned', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          fileName: file.name,
          fileType: file.type,
          fileSize: file.size,
        }),
      });
      if (!authResponse.ok) {
        throw new Error('Failed to obtain upload authorization.');
      }
      const { uploadUrl, storageKey } = await authResponse.json();
      // Step 2: Upload raw file directly to storage via HTTP PUT
      setStatus('Uploading directly to cloud storage...');
      const uploadResponse = await fetch(uploadUrl, {
        method: 'PUT',
        headers: {
          'Content-Type': file.type,
        },
        body: file,
      });
      if (!uploadResponse.ok) {
        throw new Error('Direct upload to storage provider failed.');
      }
      // Step 3: Register completion with Next.js backend
      setStatus('Finalizing upload registration...');
      await fetch('/api/upload/complete', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ storageKey, fileName: file.name }),
      });
      setStatus(`Upload complete: ${file.name}`);
    } catch (err) {
      setStatus(err instanceof Error ? err.message : 'Upload failed');
    } finally {
      setUploading(false);
    }
  }
  return (
    <div className="p-6 border rounded-lg max-w-md mx-auto">
      <h3 className="font-semibold text-lg mb-2">Direct Cloud File Upload</h3>
      <p className="text-sm text-gray-600 mb-4">
        Bypasses Next.js serverless payload limits. Supports files up to `500MB`.
      </p>
      <input
        type="file"
        disabled={uploading}
        onChange={handleFileSelection}
        className="block w-full text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded-md file:border-0 file:text-sm file:font-semibold file:bg-blue-50 file:text-blue-700 hover:file:bg-blue-100"
      />
      {status && <p className="mt-3 text-sm text-gray-700">{status}</p>}
    </div>
  );
}
```

### Resumable Chunked Uploads for Gigabyte-Scale Files

When working with massive video files, disk images, or raw audio stems that measure hundreds of megabytes or gigabytes, even a direct single-request upload becomes brittle. If a network interruption occurs midway through a multi-gigabyte transfer, the entire upload must restart from the beginning.

Resumable upload protocols solve this problem by slicing the file into smaller chunks (typically `5MB` to `10MB` each) on the client side. Each chunk transfers via an independent HTTP request. If a connection drops, the client queries the server for the last acknowledged byte offset and resumes transmission without losing progress.

## How to Manage Document Collections in Next.js AI Applications

Next.js has become a primary framework for building AI-powered software, including Retrieval-Augmented Generation (RAG) platforms, legal discovery tools, financial research portals, and autonomous agent workspaces. These applications frequently require ingesting massive document collections, such as multi-hundred-page PDF contracts, annual financial filings, and technical documentation archives.

Attempting to ingest large document corpora through Next.js Server Actions or Route Handlers introduces severe architectural failure modes:

1. **Payload and Memory Crashes:** Pushing whole PDF binders or archive files across Next.js API routes quickly hits the `1MB` Server Action or `4.5MB` Vercel serverless ceiling, crashing serverless functions and consuming costly container memory.
2. **Language Model Context Window Saturation:** Even if a file bypasses frontend API limits, passing multi-megabyte document payloads into language model prompts saturates the model context window. While frontier models accept substantial token counts, loading hundreds of pages of raw text into a prompt degrades reasoning performance, introduces needle-in-a-haystack retrieval errors, and dramatically inflates inference costs.
3. **Vendor Upload Boundaries:** AI model providers enforce their own strict boundaries on attached files. As documented in the [Anthropic Claude file upload guide](https://support.claude.com/en/articles/8241126-upload-files-to-claude), standard chat sessions accept attached files for interactive analysis, while Claude Projects accepts project files with no fixed file-count cap. However, all project knowledge must fit within Claude's context window. Attempting to attach large corpora directly into conversations or projects inevitably leads to context exhaustion warnings.

### The External Intelligent Workspace Architecture

The scalable architecture for Next.js AI applications decouples binary storage and document indexing from the application server. Instead of uploading documents through Next.js or attaching massive files directly to model prompts, your application deposits files into an external [intelligent workspace](/product/workspaces/).

Fast.io workspaces provide persistent, organization-owned storage designed specifically for human-agent collaboration and [AI storage](/product/ai-storage/). Files uploaded to a Fast.io workspace bypass serverless payload caps entirely, supporting large single-file uploads up to plan limits: `25 GB` on Starter, `50 GB` on Business, and `100 GB` on Enterprise.

When files enter a Fast.io workspace with Intelligence Mode enabled, the platform indexes their contents automatically for hybrid search, combining full-text, semantic, and metadata filtering. There is no need to deploy or maintain a separate vector database, chunking pipeline, or embedding model.

### Connecting Next.js and AI Agents Over Model Context Protocol (MCP)

Rather than passing raw document bytes into Next.js endpoints, your AI assistants and backend workflows connect to Fast.io workspaces using the Model Context Protocol (MCP). Teams can review [storage for agents](/storage-for-agents/) and connect to the remote Fast.io MCP server over Streamable HTTP with dedicated endpoints tailored to each client environment:

- **Coding Agents and IDEs:** Connect coding agents such as Claude Code, Cursor, Cline, and Copilot agent mode to `https://mcp.fast.io/mcp/code`.
- **General Assistants and Claude Apps:** Connect Claude web, Claude Desktop, and autonomous agents to `https://mcp.fast.io/mcp/tools`.
- **ChatGPT and Codex:** Connect via the Fast.io plugin or custom MCP endpoint at `https://mcp.fast.io/mcp/operations`.

When a user asks a question about a 200-page lease or a multi-file documentation set in your Next.js application, the AI model queries the workspace index through MCP. The model retrieves only the precise paragraphs and data points needed to answer the prompt, backed by verified citations.

For teams managing multi-provider document collections, Fast.io Cloud Sync connects Google Drive, Dropbox, Box and OneDrive folders to a workspace, one-way or two-way, on a schedule or on demand. Every file keeps complete per-file version history, while a detailed activity log tracks all storage changes, moves, and deletions across your organization. [Fast.io Collaboration](/product/collaboration/) tools and monthly plans start with a 14-day free trial on [Fast.io pricing](/pricing/) (credit card required).

Next.js backends remain fast, lightweight, and completely free of 413 payload errors, while AI models operate with instant access to indexed corporate knowledge.

## Frequently asked questions

### How to increase Server Action file upload limit in Next.js?

To increase the Server Action file upload limit in Next.js, add the serverActions.bodySizeLimit property to your next.config.js or next.config.ts file. For example, configure `serverActions: { bodySizeLimit: '10mb' }` in your configuration to expand the permitted payload size. If you are using an earlier Next.js 14 release, place the configuration under experimental.serverActions.bodySizeLimit. Make sure to rebuild your application after changing this configuration.

### What is the maximum file size upload in Next.js App Router?

In the Next.js App Router, Server Actions enforce a default `1MB` request body limit that you can increase in next.config.js. Route Handlers do not impose a default framework parsing ceiling in Next.js core. However, when deployed to Vercel, both Server Actions and Route Handlers are bounded by Vercel's hard platform ceiling of `4.5MB` for serverless request bodies. For files larger than `4.5MB`, implement direct-to-storage uploads using presigned URLs.

### How to handle large document uploads in Next.js AI applications?

To handle large document uploads in Next.js AI applications, avoid passing multi-megabyte files through serverless endpoints or stuffing raw documents into model prompts. Instead, store documents in an external cloud workspace like Fast.io with Intelligence Mode enabled. The workspace indexes documents for hybrid semantic and keyword search. AI agents can then query the workspace over Model Context Protocol (MCP) to retrieve relevant excerpts without triggering payload or context window limits.

### Why do I still get an HTTP 413 error after configuring bodySizeLimit in next.config.js?

If you configured bodySizeLimit in next.config.js but still encounter an HTTP 413 error, three common issues may be responsible: first, multipart/form-data adds `10KB` to `50KB` of header and boundary overhead, pushing an exact-size file over your configured limit; second, your application is deployed to Vercel or AWS Lambda, where platform proxy limits (such as Vercel's `4.5MB` ceiling) override application settings; third, an upstream reverse proxy like Nginx enforces its own client_max_body_size.

### Does export const config = { api: { bodyParser: false } } work in Next.js App Router Route Handlers?

No, the export const config directive only applied to the legacy Pages Router (pages/api) and has no effect in the Next.js App Router. In App Router Route Handlers, Next.js does not automatically parse request bodies with a built-in bodyParser. Instead, Route Handlers receive standard Web Request objects, allowing you to parse form data with request.formData() or consume the raw stream directly via request.body.

### What is the difference between an HTTP 413 error and an HTTP 504 Gateway Timeout during file uploads?

An HTTP 413 Payload Too Large error occurs immediately when an incoming request body exceeds the size limit configured on the server, reverse proxy, or Next.js Server Action buffer. In contrast, an HTTP 504 Gateway Timeout occurs when an upload takes longer to transmit or process than the serverless function's execution timeout window (such as Vercel's 15-second default), even if the file size remains well below the 413 limit.

## Sources

- [Next.js Documentation: serverActions.bodySizeLimit](https://nextjs.org/docs/app/api-reference/config/next-config-js/serverActions): Next.js Server Actions enforce a strict default request body size limit of 1MB to prevent server resource consumption and memory exhaustion.
- [Vercel Documentation: Function Limitations](https://vercel.com/docs/functions/limitations): Vercel serverless functions enforce a maximum request and response payload limit of 4.5MB per invocation.

## About Fast.io

Fast.io provides shared workspaces where people and AI agents work on the same files, with built-in semantic search and citation-backed chat over what they hold. Agents reach it through a remote MCP server, a REST API at https://api.fast.io/current/, and a command line client published on npm as @vividengine/fastio-cli. MCP setup is at https://mcp.fast.io/docs: Claude and most MCP clients connect to https://mcp.fast.io/mcp/tools, ChatGPT to https://mcp.fast.io/mcp/operations, and coding agents to https://mcp.fast.io/mcp/code.
