Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

184
Views
How to safely modify globals / write files in express POST request?

I am writing my first very simple express server for data a collection purpose. This seems like a beginner question but I failed to find an answer so far. The data is very small (less than 500 integers) and will never grow, but it should be able to be changed through POST requests.

I essentially (slightly simplified) want to:

  • Have the data in a .json file that is loaded when the server starts.
  • On a POST request, modify the data and update the .json file.
  • On a GET request, simply send the .json containing the data.

I don't want to use a database for this as the data is just a single small array that will never grow in size. My unclarities are mainly how to handle modifying the global data and file reading / writing safely, i.e. concurrency and how exactly does Node run the code.

I have the following

const express = require('express');
const fs = require('fs');

let data = JSON.parse(fs.readFileSync('./data.json'));

const app = express();
app.listen(3000);
app.use(express.json());

app.get("/", (req, res) => {
  res.sendFile('./data.json', { root: __dirname });
});

app.post("/", (req, res) => {
  const client_data = req.body;
  // modify global data
  fs.writeFileSync("./data.json", JSON.stringify(data), "utf8");
});

Now I have no idea if or why this is safe to do. For example, modifying the global data variable and writing to file. I first assumed that requests cannot run concurrently without explicitly using async functions, but that seems to not be the case: I inserted this:

const t = new Date(new Date().getTime() + 5000);
while(t > new Date()){}

into the app.post(.. call to try and understand how this works. I then made simultaneous POST requests and they finished at the same time, which I did not expect.

Clearly, the callback I pass to app.post(.. is not executed all at once before other POST requests are handled. But then I have a callback running concurrently for all POST requests, and modifying the global data and writing to file is unsafe / a race condition. Yet all code I could find online did it in this manner.

Am I correct here? If so, how do I safely modify the data and write it to file? If not, I don't understand how this code is safe at all?

about 4 years ago · Juan Pablo Isaza
1 answers
Answer question

0

Code like that actually opens up your system to race conditions. Node actually runs that code in a single-threaded kind of way, but when you start opening files and all that stuff, it gets processed by multiple threads (opening files are not Node processes, they are delegated to the OS).

If you really, really want to use files as your global data, then I guess you can use an operating system concept called Mutual Exclusions. Basically, its a 'lock' used to prevent race conditions by forcing processes to wait while something is currently accessing the shared resource (or if the shared resource is busy). In Node, this can be implemented in many ways, but one recommendation is to use async-mutex library to handle concurrent connections and concurrent data modifications. You can do something like:

const express = require('express');
const fs = require('fs');
const Mutex = require('async-mutex').Mutex;

// Initializes shared mutual exclusion instance.
const mutex = new Mutex()

let data = JSON.parse(fs.readFileSync('./data.json'));

const app = express();
app.listen(3000);
app.use(express.json());

app.get("/", (req, res) => {
  res.sendFile('./data.json', { root: __dirname });
});

// Turn this into asynchronous function.
app.post("/", async (req, res) => {
  const client_data = req.body;

  const release = await mutex.acquire();
  try {
    fs.writeFileSync('./data.json', JSON.stringify(data), 'utf8');
    res.status(200).json({ status: 'success' });
  } catch (err) {
    res.status(500).json({ err });
  finally {
    release();
  }
});

You can also use Promise.resolve() in order to achieve similar results with the async-mutex library.

Note that I recommend you to use a database instead, as it is much better and abstracts a lot of things for you.

References:

  • Node.js Race Conditions
about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!