---
title: Processing Data Chunks
description: Learn how to create an API endpoint that processes data chunks.
url: /kb/guide/processing-data-chunks
canonical_url: "https://vercel.com/kb/guide/processing-data-chunks"
published: 2025-11-04
last_updated: 2025-11-11
authors: DX Team
related:
  - /docs/fundamentals/what-is-streaming
install_vercel_plugin: npx plugins add vercel/vercel-plugin
---
<!-- docsgraph:related -->
## Related pages

> **For AI agents:** Follow these links to understand how this page connects to the rest of the Vercel ecosystem. For the full cross-link map (inbound, outbound, prerequisites, and semantic neighbors), see the .graph.md link below.

- [Streaming](https://vercel.com/docs/functions/streaming-functions?from=related) — Learn how to stream responses from Vercel Functions.
- [Streaming](https://vercel.com/docs/ai-gateway/sdks-and-apis/openresponses/streaming?from=related) — Stream responses token by token using the OpenResponses API.
- [Streaming](https://vercel.com/docs/ai-gateway/sdks-and-apis/anthropic-messages-api/streaming?from=related) — Stream Anthropic Messages API responses token by token as they are generated.
- [Streaming](https://vercel.com/docs/ai-gateway/sdks-and-apis/openai-chat-completions/streaming?from=related) — Stream OpenAI Chat Completions responses token by token as they are generated.
- [Streaming](https://vercel.com/docs/ai-gateway/sdks-and-apis/responses/streaming?from=related) — Stream tokens as they are generated with the OpenAI Responses API.
- [Streaming in web applications](https://vercel.com/kb/guide/what-is-streaming?from=related) — Learn how streaming works in web applications. Explore benefits, use cases, and implementation details with Vercel Funct
- [Stream Protocols](https://ai-sdk.dev/docs/ai-sdk-ui/stream-protocol?from=related)
- [Express](https://ai-sdk.dev/cookbook/api-servers/express?from=related)
- [Handling Backpressure](https://vercel.com/kb/guide/handling-backpressure?from=related) — Learn how to handle backpressure by pushing data into a steam as it's needed, rather than as it's ready.
- [Streaming responses from LLMs](https://vercel.com/kb/guide/streaming-from-llm?from=related) — Learn how to use the AI SDK to stream LLM responses.
- [How to ship an Express app on Vercel](https://vercel.com/kb/guide/ship-a-express-app-on-vercel?from=related) — Deploy an Express app to Vercel with zero configuration. Configure response streaming, middleware, cron jobs, the Bun ru

Full cross-link map for this page: [/kb/guide/processing-data-chunks.graph.md](/kb/guide/processing-data-chunks.graph.md)
<!-- /docsgraph:related -->


Chunks in web streams are fundamental data units that can be of many different types depending on the content, such as `String` for text or `Uint8Array` for binary files. While standard Function responses contain full payloads of data processed on the server, streamed responses typically send data in chunks over time.

To do this, you [create a ReadableStream](#create-a-readablestream) and add a data source, then [transform](#transform-the-stream's-data-chunks) the stream's data chunks before they're read by the client. Finally, you [write stream the data chunk by chunk](#write-stream-the-data-chunk-by-chunk) as a Function response.

Jump to the [full example](#full-example) to see the finished recipe.

### Create a ReadableStream

Create a [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) and add a data source. In this case, you'll create your own data by encoding text with [`TextEncoder`](https://developer.mozilla.org/en-US/docs/Web/API/TextEncoder):

```ts
// TextEncoder objects turn text content
// into streams of UTF-8 characters.
// You'll add this encoder to your stream
const encoder = new TextEncoder();
// This is the stream object, which clients can read from
// when you send it as a Function response
const readableStream = new ReadableStream({
  // The start method is where you'll add the stream's content
  start(controller) {
    const text = 'Stream me!';
    // Queue the encoded content into the stream
    controller.enqueue(encoder.encode(text));
    // Prevent more content from being
    // added to the stream
    controller.close();
  },
});
```
```js
// TextEncoder objects turn text content
// into streams of UTF-8 characters.
// You'll add this encoder to your stream
const encoder = new TextEncoder();
// This is the stream object, which clients can read from
// when you send it as a Function response
const readableStream = new ReadableStream({
  // The start method is where you'll add the stream's content
  start(controller) {
    const text = 'Stream me!';
    // Queue the encoded content into the stream
    controller.enqueue(encoder.encode(text));
    // Prevent more content from being
    // added to the stream
    controller.close();
  },
});
```

### Transform the stream's data chunks

You then need to transform the stream's data chunks before they're read by the client. First, you'll decode the chunks with `TextDecoder`, then transform the text to uppercase before encoding the text again:

```js
// TextDecoders can decode streams of
// encoded content. You'll use this to
// transform the streamed content before
// it's read by the client
const decoder = new TextDecoder();
// before they're read in the client
// TransformStreams can transform a stream's chunks
const transformStream = new TransformStream({
  transform(chunk, controller) {
    // Decode the content, so it can be transformed
    const text = decoder.decode(chunk);
    // Make the text uppercase, then encode it and
    // add it back to the stream
    controller.enqueue(encoder.encode(text.toUpperCase()));
  },
});
```
```ts
// TextDecoders can decode streams of
// encoded content. You'll use this to
// transform the streamed content before
// it's read by the client
const decoder = new TextDecoder();
// TransformStreams can transform a stream's chunks
// before they're read in the client
const transformStream = new TransformStream({
  transform(chunk, controller) {
    // Decode the content, so it can be transformed
    const text = decoder.decode(chunk);
    // Make the text uppercase, then encode it and
    // add it back to the stream
    controller.enqueue(encoder.encode(text.toUpperCase()));
  },
});
```

### Write stream the data chunk by chunk

Finally, write stream the data chunk by chunk as a Function response:

```ts
// Finally, send the streamed response. Result:
// "STREAM ME!" will be displayed in the client
return new Response(readableStream.pipeThrough(transformStream), {
  headers: {
    'Content-Type': 'text/html; charset=utf-8',
  },
});
```
```js
// Finally, send the streamed response. Result:
// "STREAM ME!" will be displayed in the client
return new Response(readableStream.pipeThrough(transformStream), {
  headers: {
    'Content-Type': 'text/html; charset=utf-8',
  },
});
```

### Full example

The final file will look like this:

```ts
// This method must be named GET
export async function GET() {
  // TextEncoder objects turn text content
  // into streams of UTF-8 characters.
  // You'll add this encoder to your stream
  const encoder = new TextEncoder();
  // This is the stream object, which clients can read from
  // when you send it as a Function response
  const readableStream = new ReadableStream({
    // The start method is where you'll add the stream's content
    start(controller) {
      const text = 'Stream me!';
      // Queue the encoded content into the stream
      controller.enqueue(encoder.encode(text));
      // Prevent more content from being
      // added to the stream
      controller.close();
    },
  });

  // TextDecoders can decode streams of
  // encoded content. You'll use this to
  // transform the streamed content before
  // it's read by the client
  const decoder = new TextDecoder();
  // TransformStreams can transform a stream's chunks
  // before they're read in the client
  const transformStream = new TransformStream({
    transform(chunk, controller) {
      // Decode the content, so it can be transformed
      const text = decoder.decode(chunk);
      // Make the text uppercase, then encode it and
      // add it back to the stream
      controller.enqueue(encoder.encode(text.toUpperCase()));
    },
  });

  // Finally, send the streamed response. Result:
  // "STREAM ME!" will be displayed in the client
  return new Response(readableStream.pipeThrough(transformStream), {
    headers: {
      'Content-Type': 'text/html; charset=utf-8',
    },
  });
}
```
```js
// This method must be named GET
export async function GET() {
  // TextEncoder objects turn text content
  // into streams of UTF-8 characters.
  // You'll add this encoder to your stream
  const encoder = new TextEncoder();
  // This is the stream object, which clients can read from
  // when you send it as a Function response
  const readableStream = new ReadableStream({
    // The start method is where you'll add the stream's content
    start(controller) {
      const text = 'Stream me!';
      // Queue the encoded content into the stream
      controller.enqueue(encoder.encode(text));
      // Prevent more content from being
      // added to the stream
      controller.close();
    },
  });

  // TextDecoders can decode streams of
  // encoded content. You'll use this to
  // transform the streamed content before
  // it's read by the client
  const decoder = new TextDecoder();
  // TransformStreams can transform a stream's chunks
  // before they're read in the client
  const transformStream = new TransformStream({
    transform(chunk, controller) {
      // Decode the content, so it can be transformed
      const text = decoder.decode(chunk);
      // Make the text uppercase, then encode it and
      // add it back to the stream
      controller.enqueue(encoder.encode(text.toUpperCase()));
    },
  });

  // Finally, send the streamed response. Result:
  // "STREAM ME!" will be displayed in the client
  return new Response(readableStream.pipeThrough(transformStream), {
    headers: {
      'Content-Type': 'text/html; charset=utf-8',
    },
  });
}
```

> If you're not using a framework, you must either add `"type": "module"` to your `package.json` or change your JavaScript Functions' file extensions from `.js` to `.mjs`

Build your app and visit `localhost:3000/api/chunk-example`. You should see the text `"STREAM ME!"` in the browser.

### Run your app locally

Run your app locally and visit `localhost:3000/api/data-chunks`. You should see the text `"STREAM ME!"` in the browser.

See [understanding chunks](/docs/fundamentals/what-is-streaming#understanding-chunks) to learn more.

## More resources

- [Streaming on Vercel](/docs/fundamentals/what-is-streaming)
  
- [Vercel AI SDK](https://sdk.vercel.ai/docs)