Node.JS | Atomic Operations

An atomic operation is a single, indivisible action that is performed on data. It is a type of operation that guarantees that the operation is completed in its entirety or not at all, and no other operation can interfere with it. This means that while the operation is in progress, no other process or thread can access or modify the same data. Atomic operations are used to ensure that data integrity is maintained, and that no conflicts occur when multiple processes or threads are accessing the same data.

An atomic operation in a Node.js server refers to a single, indivisible action that is performed on data. This is important in situations where multiple processes or threads are accessing the same data and you want to ensure that no conflicts occur. Examples of atomic operations in Node.js include incrementing a counter, updating a specific field in a database, or appending data to a file.

Here’s an example of an atomic operation in Node.js using the fs module to append data to a file:

const fs = require('fs');

// Function to atomically append data to a file
function atomicAppend(file, data) {
    // Use the `fs.open` method to open the file with the `a` (append) flag
    fs.open(file, 'a', (err, fd) => {
        if (err) throw err;

        // Use the `fs.flock` method to acquire an exclusive lock on the file
        fs.flock(fd, 'ex', (err) => {
            if (err) throw err;

            // Use the `fs.write` method to write the data to the file
            fs.write(fd, data, (err) => {
                if (err) throw err;

                // Release the lock and close the file
                fs.flock(fd, 'un', (err) => {
                    if (err) throw err;
                    fs.close(fd, (err) => {
                        if (err) throw err;
                    });
                });
            });
        });
    });
}

This function atomically appends data to a file by first opening the file with the ‘a’ (append) flag, then acquiring an exclusive lock on the file using the fs.flock method, writing the data to the file, then releasing the lock and closing the file. This ensures that no other process can write to the file while this process has the lock, and that the data is written to the file in its entirety or not at all.

Note that on Windows, fs.flock does not work, instead you can use fs.writeFile with the w flag and the fs.appendFile with the a flag, it will ensure atomic write or append operation on the file.


Here’s an example of an atomic operation in Node.js using the mongodb driver to update a specific field in a MongoDB collection:

const MongoClient = require('mongodb').MongoClient;

// Connect to MongoDB
MongoClient.connect('mongodb://localhost:27017/mydb', (err, client) => {
    if (err) throw err;

    const db = client.db('mydb');
    const collection = db.collection('users');

    // Function to atomically increment a user's score
    function atomicIncrement(username, amount) {
        // Use the `findOneAndUpdate` method to find a user by username
        // and increment their score by a specific amount
        collection.findOneAndUpdate(
            { username: username },
            { $inc: { score: amount } },
            { returnOriginal: false },
            (err, result) => {
                if (err) throw err;
                console.log(result.value);
            }
        );
    }
});

This function atomically increments a user’s score by a specific amount by using the findOneAndUpdate method. The method first finds the user by their username and then updates their score using the $inc operator. The returnOriginal: false option returns the updated document, rather than the original. This ensures that only one operation is performed on the user's score, and that the new value is the correct value.

You can also use the findOneAndUpdate method with option {upsert: true} to create a document if it doesn't exist, and update it if it does.

You can also use transactions in MongoDB if you want to perform multiple operations atomically in a single transaction.