0PricingLogin
NestJS Enterprise Backend APIs · Lesson

Streaming Large Responses with StreamableFile

Serve large downloads efficiently using StreamableFile and Node readable streams to avoid buffering.

The Buffering Problem

When a controller returns a large file, the naive approach is to read the whole file into memory and send it back:

  • fs.readFileSync('huge.zip') loads every byte into RAM before the first byte reaches the client.
  • A 2 GB export served to 50 concurrent users can exhaust heap and crash the process.

Streaming solves this: read the file in small chunks and pipe them to the response as they arrive, keeping memory usage flat regardless of file size.

What StreamableFile Is

NestJS ships a StreamableFile class. You wrap a Node.js Readable stream (or a Buffer) in it and return it from a controller handler.

  • Nest detects the StreamableFile return value and pipes the underlying stream to the HTTP response for you.
  • It works across both Express and Fastify adapters without you touching res.pipe() manually.

This keeps your handler declarative while still streaming chunk-by-chunk.

import { Controller, Get, StreamableFile } from '@nestjs/common';
import { createReadStream } from 'fs';
import { join } from 'path';

@Controller('files')
export class FilesController {
  @Get('report')
  getReport(): StreamableFile {
    const file = createReadStream(join(process.cwd(), 'report.pdf'));
    return new StreamableFile(file);
  }
}

All lessons in this course

  1. Multipart Uploads with Multer Interceptors
  2. Streaming Large Responses with StreamableFile
  3. Direct-to-S3 Uploads with Presigned URLs
  4. Image Processing Pipelines with Sharp
← Back to NestJS Enterprise Backend APIs