How to create writable streams in Node.js

Creating custom writable streams in Node.js enables efficient data consumption and processing for file operations, data transformation, and output handling. As the creator of CoreUI with over 11 years of Node.js development experience, I’ve built numerous writable streams for log processing, data export systems, and real-time analytics. From my expertise, the most reliable approach is extending the Writable class and implementing the _write() method to handle incoming data chunks. This pattern provides complete control over data consumption, processing, and output formatting for scalable server applications.

Extend the Writable class and implement the _write() method to create custom data-consuming streams.

const { Writable } = require('stream')
const fs = require('fs')

class LogWriter extends Writable {
  constructor(filename, options = {}) {
    super(options)
    this.filename = filename
    this.writeStream = fs.createWriteStream(filename, { flags: 'a' })
  }

  _write(chunk, encoding, callback) {
    const timestamp = new Date().toISOString()
    const logEntry = `[${timestamp}] ${chunk.toString()}\n`

    this.writeStream.write(logEntry, (error) => {
      callback(error)
    })
  }

  _destroy(error, callback) {
    this.writeStream.end()
    callback(error)
  }
}

const logger = new LogWriter('app.log')
logger.write('Application started')
logger.write('User logged in')

Here the LogWriter class extends Writable and implements _write() to process incoming data chunks. The method receives the data chunk, encoding, and a callback function that must be called when processing is complete. Each log entry gets timestamped and written to a file. The _destroy() method handles cleanup when the stream is destroyed, ensuring proper resource management.

Best Practice Note:

This is the same approach we use in CoreUI backend services for structured logging, data export processing, and real-time data analytics pipelines. Always call the callback function in _write() to maintain proper stream flow control, and implement _destroy() for proper resource cleanup in production applications.


Speed up your responsive apps and websites with fully-featured, ready-to-use open-source admin panel templates—free to use and built for efficiency.


About the Author