NestJS — Enterprise Node.js

Server-Sent Events & Streaming Files

18 min Lesson 61 of 80

Server-Sent Events & Streaming Files

WebSockets are not the only real-time option. Server-Sent Events stream one-way updates over normal HTTP, and StreamableFile lets a controller return large files without loading the whole payload into memory.

Core idea

This feature is about controlling how the application is organized and how it behaves at runtime. These are the points a developer should understand before using it in a real project:

  • SSE is ideal for progress updates, notifications, dashboards, and logs where the server pushes and the browser listens.
  • @Sse() handlers return an Observable of MessageEvent objects.
  • StreamableFile wraps a readable stream and integrates with Nest response handling.
  • Set correct Content-Type, Content-Disposition, and cache headers for downloads.
  • For very large or private files, consider pre-signed object-storage URLs instead of routing every byte through the app server.

Practical example

The following example shows the idea in a practical NestJS project. The goal is not to memorize the snippet, but to understand where it belongs in the architecture:

@Controller('jobs') export class JobsController { @Sse(':id/events') events(@Param('id') id: string): Observable<MessageEvent> { return this.jobsService.progress$(id).pipe( map((progress) => ({ data: progress })), ); } @Get(':id/export') download(@Param('id') id: string): StreamableFile { const stream = this.exportsService.openReadStream(id); return new StreamableFile(stream, { type: 'text/csv' }); } }
Design note: SSE is simpler than WebSockets when communication is one-way. Streaming files is safer than reading them into buffers because memory use stays bounded.

Production checklist

  • Use SSE for one-way live updates and WebSockets for bidirectional collaboration.
  • Close observables when clients disconnect.
  • Set download headers explicitly.
  • Avoid buffering large exports in memory.
Rule of thumb: If the feature makes boundaries clearer and tests easier, it is probably the right choice. If it hides dependencies or makes tracing harder, redesign.

Summary

This lesson covers an advanced NestJS area that matters when building enterprise applications. Focus on clear boundaries, testable behavior, and choosing the right tool for the context instead of using every feature everywhere.