VOOZH about

URL: https://thenewstack.io/how-to-deal-with-race-conditions/

⇱ How to Deal with Race Conditions - The New Stack


TNS
SUBSCRIBE
Join our community of software engineering leaders and aspirational developers. Always stay in-the-know by getting the most important news and exclusive content delivered fresh to your inbox to learn more about at-scale software development.
REQUIRED
It seems that you've previously unsubscribed from our newsletter in the past. Click the button below to open the re-subscribe form in a new tab. When you're done, simply close that tab and continue with this form to complete your subscription.
The New Stack does not sell your information or share it with unaffiliated third parties. By continuing, you agree to our Terms of Use and Privacy Policy.
Welcome and thank you for joining The New Stack community!
Please answer a few simple questions to help us deliver the news and resources you are interested in.
REQUIRED
REQUIRED
REQUIRED
REQUIRED
REQUIRED
Great to meet you!
Tell us a bit about your job so we can cover the topics you find most relevant.
REQUIRED
REQUIRED
REQUIRED
REQUIRED
REQUIRED
Welcome!

We’re so glad you’re here. You can expect all the best TNS content to arrive Monday through Friday to keep you on top of the news and at the top of your game.

What’s next?

Check your inbox for a confirmation email where you can adjust your preferences and even join additional groups.

Follow TNS on your favorite social media networks.

Become a TNS follower on LinkedIn.

Check out the latest featured and trending stories while you wait for your first TNS newsletter.

PREV
1 of 2
NEXT
VOXPOP
As a JavaScript developer, what non-React tools do you use most often?
Angular
0%
Astro
0%
Svelte
0%
Vue.js
0%
Other
0%
I only use React
0%
I don't use JavaScript
0%
Thanks for your opinion! Subscribe below to get the final results, published exclusively in our TNS Update newsletter:
NEW! Try Stackie AI
From clobbered drafts to real-time sync
Apr 14th 2026 10:00am, by David Moore
TypeScript 6.0 RC arrives as a bridge to a faster future
Mar 14th 2026 9:00am, by Darryl K. Taft
Mastra empowers web devs to build AI agents in TypeScript
Jan 28th 2026 11:00am, by Loraine Lawson
2021-11-12 08:45:13
How to Deal with Race Conditions
contributed,sponsor-logdna,sponsored,sponsored-post-contributed,
DevOps / Security / Software Development

How to Deal with Race Conditions

"Race conditions" refers to bugs that occur due to the timing or order-of-execution of multiple operations. Here's how to deal with them.
Nov 12th, 2021 8:45am by Mike Del Tito
👁 Featued image for: How to Deal with Race Conditions
Photo by cottonbro from Pexels.
LogDNA sponsored this post.
“Race conditions” refers to bugs that occur due to the timing or order of execution of multiple operations. This is a fairly broad class of bugs that can present themselves in very different ways, depending on the problem space. In many cases, they can be difficult to identify and/or reproduce, even if the solution might be simple.

TOCTOU

“Time-of-check to time-of-use” (TOCTOU) describes a type of race condition that occurs when the state of a resource changes between checking its state and using the result. TOCTOU is usually discussed in the context of filesystem operations, but variations are possible in many areas of the systems we build. The common example of a TOCTOU race condition is checking if a file is accessible and then reading it:
let exists = await fs.access(path_to_file)
if (exists) {
 const data = await fs.readFile(path_to_file)
 ...
}

If the file is deleted or otherwise modified after the initial check, at best you will end up with an unhandled exception. At worst, you could be opening the door to a security vulnerability. Instead: Skip the access check, wrap the readFile in a try/catch and handle any errors there.

Atomicity

Normally we talk about “updating atomically” in the context of database systems. Consider the following contrived example:
const user = db.users.findOne(id)
if (user.role === 'admin') {
 user.superPowers = true
 user.save()
}

See the problem? The user is fetched from the database, some logic is performed, then a query is executed to update the user. This is a non-atomic operation, however, and there is no guarantee that the user’s role is still set to “admin” in the database between the time of the check and the update. In this fake example, the consequence might be a security vulnerability in the application; and in a real-world scenario, it might be even more difficult to notice depending on the complexity of the system. Instead: Craft an atomic update query that performs the update in a single statement.

Shared State

Mike Del Tito
Mike is an experienced senior developer at LogDNA, with a demonstrated history of designing, delivering and leading teams in the development of web-based software applications.
Although Node.js is single-threaded, working with shared resources and data structures asynchronously requires the same level of care as needed in multi-threaded systems. Here’s another example: https://repl.it/@MikeDel2/set-data-race?lite=true At a quick glance, you might expect this to always output the first value of 1, but the program can print a different value every time (try it!). Even if it’s easy to spot the issue here in an isolated example, consider a more complex concurrent program with a similar goal of doing some work only when a precondition is met. You might have multiple asynchronous workers that need to:
  • Open a write stream for a specific file for all workers to write to.
  • Create a record in a database if it doesn’t already exist.
  • Memoize the result of a very expensive operation.
In all of these scenarios, you cannot assume the state of the resource you are working with will remain the same between the check and the use. Variations of this specific “create if not exist” race condition have popped up several times recently in third-party code and even our own.
Mezmo, formerly LogDNA, is an observability platform to manage and take action on your data. It ingests, processes, and routes log data to fuel enterprise-level application development and delivery, security, and compliance use cases.
Learn More
The latest from LogDNA

Counter Measures

Avoiding race conditions not only requires some thought about what your code is doing, but also about how other parts of the system will use your code. There are no silver bullets here, but in addition to being thoughtful about concurrent design, here are some tips:
  • Perform database updates atomically. Do not rely on previously queried information about the record you are updating to craft your update query.
  • In general, avoid sharing “global” state whenever possible, but especially with concurrency. Think about the implications of simultaneous access to data structures and how that affects the logic of the program or the correctness of the data itself.
  • If sharing state among concurrent routines is required, consider introducing a mutex (mutually exclusive) or another locking mechanism to control access to the shared resource. This comes at the expense of complexity, but is sometimes unavoidable.
Mezmo, formerly LogDNA, is an observability platform to manage and take action on your data. It ingests, processes, and routes log data to fuel enterprise-level application development and delivery, security, and compliance use cases.
Learn More
The latest from LogDNA
TRENDING STORIES
Mike is an experienced senior developer at LogDNA, with a demonstrated history of designing, delivering and leading teams in the development of web-based software applications.
Read more from Mike Del Tito
LogDNA sponsored this post.
SHARE THIS STORY
TRENDING STORIES
TNS owner Insight Partners is an investor in: Pragma.
SHARE THIS STORY
TRENDING STORIES
TNS DAILY NEWSLETTER Receive a free roundup of the most recent TNS articles in your inbox each day.
The New Stack does not sell your information or share it with unaffiliated third parties. By continuing, you agree to our Terms of Use and Privacy Policy.