
Hello humans.
Welcome to this week’s Sloth Bytes. I hope you had a nice week.

Learn AI in 5 minutes a day
This is the easiest way for a busy person wanting to learn AI in as little time as possible:
Sign up for The Rundown AI newsletter
They send you 5-minute email updates on the latest AI news and how to use it
You learn how to become 2x more productive by leveraging AI

What the Heck Is a Race Condition?

Let me be honest with you all.
I know absolutely NOTHING about parallelism and concurrency….
Hey don’t laugh. I use JavaScript, so it’s not surprising.
Anyways, I decided to study these concepts. (One of the reasons why I love this newsletter is I can share what I learn with you all 😁)
Alright buddy. I don’t care. Give me the info.
Alright fine.
There’s one specific concept I wanted to understand because I always hear about it, but never fully understood it.
It was one of those concepts where someone says it and I just nod.
Race conditions.
What is a Race Condition?
Let me paint a picture for you.
Imagine two operations can both observe and update the same piece of state before either one knows what the other did.
They might be threads, async tasks, HTTP requests, database transactions, workers on different machines, or even two browser requests arriving close together.
One increments, the other resets. You hit run.
And the result?
Sometimes it works. Sometimes it break. Sometimes it just… acts weird.
Welcome to the painful world of concurrency!
Race conditions are a common problem that doesn’t always crash your code but makes it dangerously unpredictable.
Technical explanation: A race condition happens when the correctness of a program depends on the relative timing or ordering of operations that are not properly coordinated. Shared mutable state is a common ingredient, but multiple CPU threads are not required.
Analogy:
Imagine two people trying to write on the same whiteboard at the same time. One’s trying to write “Hello,” the other “Goodbye.”
Depending on who starts or finishes first, you could end up with “Hellobye,” “Goodlo,” or complete gibberish.
Where Do Race Conditions Happen?
Multithreaded programs sharing mutable memory
Async code where requests/tasks finish in a different order than they started
Databases when concurrent transactions read and update the same rows
Distributed systems where multiple workers/services process related events
Frontends where an older network response can arrive after a newer one and overwrite fresher state
Common real-world examples:
Two requests both read inventory = 1 and both successfully sell the “last” item.
Two workers increment the same counter using read → add → write and one update gets lost.
A user changes a search query twice; the slower first request finishes last and replaces results for the newer query.
Two financial operations update the same balance without the required transaction/isolation guarantees.
Why Are Race Conditions Dangerous?
Because they’re sneaky.
They don’t always cause an error.
They’re hard to reproduce.
They make your software behave inconsistently.
Which means they can silently corrupt data or crash your program randomly after it's in production.
How Do You Prevent Them?
1. Locks / mutexes: Protect a critical section so only one thread/process holding that lock can perform a particular shared-state operation at a time. The lock does not magically protect the variable—every code path that accesses the shared invariant must follow the same synchronization rules.
Here’s a quick example:
import threading
lock = threading.Lock()
shared_value = 0
def increment():
global shared_value
# Read + modify + write happen inside one critical section.
with lock:
shared_value += 1
threads = [threading.Thread(target=increment) for _ in range(100)]
for thread in threads:
thread.start()
for thread in threads:
thread.join()
print(shared_value)This protects this process’s critical section. It does not coordinate another server or database process; distributed state needs a coordination mechanism appropriate to that system.
2. Atomic operations: Use operations that appear indivisible to competing operations—for example a database atomic increment, compare-and-swap, or Redis INCR. “Atomic” is about the concurrency boundary; it does not mean an arbitrary group of unrelated operations automatically becomes a transaction.
3. Avoid shared mutable state: Immutability, message passing, and ownership patterns can remove the thing competing operations were racing over in the first place.
4. Transactions / optimistic concurrency / constraints: For database state, use the database’s tools: transactions and isolation levels, row locks when appropriate, version columns/compare-and-swap, unique constraints, and atomic updates. Do not rely on “the requests probably won’t arrive together.”
5. Thread-safe/concurrent data structures: They can make individual operations safe, but a compound sequence can still race. “Check if key exists, then insert” is two operations unless the API provides one atomic method for the whole intent.
Race conditions do not care how clean your code looks, and tests do not prove they are gone. Timing-sensitive bugs may only appear under load or on a different machine.
They happen when you assume code will run in a specific order… but it doesn’t.
So anytime two operations can affect the same state, ask: what invariant must remain true, and what mechanism makes that update atomic/ordered enough?
If the answer is “uhhh, I guess timing?” then congratulations—you found the suspicious part.
Fix the coordination at the layer that owns the state: a lock for shared memory, an atomic primitive for counters, transactions/constraints for database invariants, cancellation/version checks for async UI requests, or idempotency/deduplication for distributed work.
If you want to keep learning
Debugging techniques — race conditions are notoriously hard to reproduce, so a disciplined debugging process matters even more.
Pure functions explained — reducing shared mutable state can eliminate entire classes of concurrency bugs.
Test doubles explained — isolate dependencies and simulate tricky timing or failure scenarios in tests.
5 system design resources — go deeper on concurrency, distributed systems, reliability, and architecture.


Thanks for the kind words!
To have a chance of being here, make sure to rate today’s newsletter!



Thanks to everyone who submitted!
bakzkndd, Apoll011, GabrielDornelas, triva03, AlePlaysDev, ShadowDara, JamesHarryT, pixelated-sys, porrrq, RelyingEarth87, ariatheroyal, E-Sieben, FredericoSRamos, SauravChandra10, jmadden21, and ElGonan.
Next Happy Year
Sloth needs your help to find out the next happy year.
A Happy Year is the year with only distinct digits (no duplicates).
Create a function that takes an integer year and returns the next happy year.
Examples
happyYear(2017)
output = 2018
# 2018 is the next happy year with all numbers being different.
happyYear(1990)
output = 2013
# 2013 is the next happy year with all numbers being different.
happyYear(2021)
output = 2031
# 2031 is the next happy year with all numbers being different.How To Submit Answers
Reply with
A link to your solution (github, twitter, personal blog, portfolio, replit, etc)
or if you’re on the web version leave a comment!
If you want to be mentioned here, I’d prefer if you sent a GitHub link or Replit!

New video should come out this week!
It’ll be about how to use AI for programming where I cover how I like to use AI, useful strategies to feel more productive, and how to use it without sacrificing too much programming skills.
That’s all from me!
Have a great week, be safe, make good choices, and have fun coding.
If I made a mistake or you have any questions, feel free to comment below or reply to the email!
See you all next week.
What'd you think of today's email?
Want to advertise in Sloth Bytes?
If your company is interested in reaching an audience of developers and programming enthusiasts, you may want to advertise with us here.






