Published on
View count

Node.js File Writing: createWriteStream vs. writeFileSync

Authors

Two Ways to Write a File in Node.js

When you're working with Node.js, you'll often need to write content to a file. The built-in fs (file system) module gives you a bunch of ways to do this, but two of the most common methods are createWriteStream and writeFileSync. They both get the job done, but they work in fundamentally different ways, and choosing the right one can make a big difference in how your application performs.

Let's break down the difference between the streaming, asynchronous createWriteStream and the simple, synchronous writeFileSync.

The Streaming Way: createWriteStream

The createWriteStream method is the tool you want to reach for when you're dealing with large amounts of data or when you need your application to stay responsive while the file is being written. It works by creating a "stream," which is like opening a pipe directly to the file on your disk. You can then send chunks of data down this pipe, one piece at a time.

This approach is asynchronous and non-blocking. This means that when you start writing to the file, your program doesn't just stop and wait for the entire process to finish. It kicks off the write operation in the background and can immediately move on to doing other things. This is incredibly important for servers and other applications that need to handle multiple tasks at once.

Because it writes data in chunks, it's also very memory-efficient. You don't have to load a giant 1GB file into your computer's RAM just to write it to disk. You can read a small chunk, write it, and then move on to the next one.

const fs = require('fs')
 
const content = 'This is a large amount of text that we are streaming to a file!'
 
// Open a "pipe" to the file
const writeStream = fs.createWriteStream('example.txt')
 
// Send our content down the pipe
writeStream.write(content, 'utf8')
 
// Close the pipe
writeStream.end()
 
// Listen for a confirmation that it's all done
writeStream.on('finish', () => {
  console.log('File writing completed.')
})
 
// Handle any potential errors
writeStream.on('error', (err) => {
  console.error('An error occurred:', err.message)
})
 
console.log('This message will appear immediately, while the file is still being written!')

The Simple Way: writeFileSync

On the other end of the spectrum is writeFileSync. The "Sync" at the end of its name tells you everything you need to know: it's synchronous and blocking.

When you call writeFileSync, your entire program will stop and wait until the file has been completely written to the disk. Nothing else can happen while it's working. This might sound bad, but for certain tasks, it's actually perfect.

This method is best when you're dealing with small files and the write operation is very quick. A great example is writing a configuration file when your application starts up. In that scenario, you want the application to wait until the config file is saved before it continues. It makes the logic simpler and more predictable.

However, writeFileSync loads the entire content of what you're writing into memory first. This is fine for a small text file, but trying to do this with a large video file would be a very bad idea and could easily crash your application.

const fs = require('fs')
 
const content = 'This is a small config value.'
 
try {
  // The program will pause here until the file is written
  fs.writeFileSync('config.txt', content, 'utf8')
  console.log('File writing completed.')
} catch (err) {
  console.error('An error occurred:', err.message)
}
 
console.log('This message will only appear after the file has been saved.')

Which One Should You Use?

Choosing between the two comes down to understanding your specific needs.

You should choose createWriteStream when:

  • You're working with large files (like log files, user uploads, or data exports).
  • Your application needs to remain responsive and handle other tasks while writing.
  • Memory usage is a concern.
  • You're dealing with a continuous stream of data, like from a network request.

You should choose writeFileSync when:

  • You're writing small files (like configuration or simple text files).
  • The operation needs to be complete before the rest of your program continues.
  • Simplicity and straightforward error handling are your top priorities.
  • You're writing a simple script where performance is not a major issue.

By understanding the difference between these two powerful methods, you can make smarter decisions about how your Node.js application handles files, leading to better performance and more reliable code.