Streams: process it piece by piece
The export that eats all your RAM
An ops teammate clicks Export all bookings and your handler does const rows = await bookings.findAll() β 400,000 rows β builds one giant CSV string in memory, and sends it. On a laptop with test data it's fine. In production, on a container with 512MB, that single request allocates a few hundred megabytes, the process hits its heap limit, and Node kills it. One export takes down the box for every other request.
The fix is to never hold the whole thing at once. A stream moves data in small chunks: read a booking, turn it into a CSV line, write that line out, drop it, read the next. Memory stays flat no matter how many rows there are, because only one chunk is in flight at a time.
The senior pitch:
Buffering is O(n) memory; streaming is O(1). If the dataset can grow, buffering is a time bomb β it works in the demo and pages you at 3am when a customer's data outgrew your heap.