Append data to a file in Node.js

Append with callback, promise, synchronous, or stream APIs, and preserve write ordering and backpressure when records matter.

Best practices
Illustration of files, modules, and dependencies

Use appendFile() for occasional additions and a write stream with { flags: 'a' } for sustained output. Both can create a missing file, but neither creates missing parent directories automatically.

Append with a callback

const fs = require('node:fs');

fs.appendFile('log.txt', 'A new line\n', 'utf8', (error) => {
  if (error) {
    console.error('Append failed:', error.message);
    return;
  }
  console.log('Append completed');
});

Appending retains the existing content. writeFile() also creates a missing file, but normally replaces existing content because its default flag is w. File creation is not the distinction between the two APIs.

Use promises or a synchronous call

In an ES module:

import { appendFile } from 'node:fs/promises';
await appendFile('log.txt', 'Another line\n', 'utf8');

For a short CommonJS script where blocking is acceptable:

const fs = require('node:fs');
fs.appendFileSync('log.txt', 'A synchronous line\n', 'utf8');

Synchronous filesystem operations block the calling JavaScript thread. Prefer asynchronous operations in request handlers, and handle their failures at the application's error boundary.

Stream repeated output

A stream avoids reopening the file for every record. This ES module uses a pipeline so backpressure and stream errors are handled together:

import { createWriteStream } from 'node:fs';
import { Readable } from 'node:stream';
import { pipeline } from 'node:stream/promises';

await pipeline(
  Readable.from(['First block\n', 'Second block\n']),
  createWriteStream('big.log', { flags: 'a', encoding: 'utf8' }),
);

For a large source, supply an iterator or stream that produces chunks as needed. Wrapping an already enormous string in a stream does not undo the memory used to create it. If you call stream.write() directly, honor a false return value by waiting for backpressure to clear, handle errors, and call end() when finished.

Workload Suitable API
A few occasional records fs.promises.appendFile
A small blocking script fs.appendFileSync
Repeated or large output A write stream with flags: 'a'

FAQ

Can writeFile append? Yes, writeFile(path, data, { flag: 'a' }) selects append mode. appendFile() makes the intent easier to recognize. Notice the singular flag for these convenience calls and plural flags for createWriteStream().

Are concurrent appends ordered? Do not assume call order becomes record order. Serialize operations or use one managed writer when ordering matters. A logical application record may involve multiple system writes; separate processes and network filesystems require additional coordination.

Why are characters corrupted? Use the same encoding when writing and reading strings. Buffer data already contains bytes; do not reinterpret binary bytes as text unless that conversion is intended.

Does completion mean the data survived a power failure? Not necessarily. Successful writing and durable storage are different guarantees. Choose explicit synchronization or an appropriate logging/storage system if durability is part of the requirement.

References

Get a tailored plan

Contact us

Join the community

Scan with WeChat
to join the community

Try Guance

Start online and pay only for what you use.

Get started

Choose a Guance plan

Code hosting