If Javascript is single threaded, how things like a clock work?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
JavaScript runs user code on a single main call stack, but that does not mean the environment can do only one thing in total. Timers, network I/O, user input, and rendering are coordinated by the runtime around that call stack. A clock works because JavaScript schedules callbacks to run later, not because it executes multiple pieces of JavaScript at the exact same instant.
Single-Threaded Means One JavaScript Call Stack
When people say JavaScript is single threaded, they usually mean one piece of JavaScript code runs at a time on the main thread. While a function is executing, nothing else can run on that same call stack until the function returns.
That means this code blocks everything else on the main thread:
If a timer callback was supposed to run during those three seconds, it must wait until the blocking loop finishes.
Timers Are Managed by the Runtime
Functions such as setTimeout and setInterval do not spawn a new JavaScript thread that runs your callback independently. Instead, the browser or Node.js runtime tracks the timer separately. When the delay expires, the runtime places the callback into a queue to be executed later when the call stack is free.
The expected output order is:
script end- about one second later,
timer fired
The timer does not interrupt the running script. It waits for the runtime to schedule the callback.
How a Clock Updates Repeatedly
A clock is usually implemented with setInterval or with a recursive setTimeout. Each tick schedules a callback, and the callback updates the page or console with the current time.
This code prints the current time once a second for five seconds. Only one callback runs at a time, but across time the runtime keeps re-queueing work.
The Event Loop Connects Everything
The event loop is the mechanism that keeps checking whether the main call stack is empty. If it is, the runtime can take the next queued callback and run it.
A simplified model looks like this:
- JavaScript runs synchronous code on the call stack.
- Timers and I/O are handled by the host environment.
- Completed callbacks are queued.
- The event loop moves queued work onto the stack when the stack is empty.
That is enough to explain clocks, button clicks, and network responses without requiring multiple JavaScript functions to execute simultaneously on the main thread.
Why Timers Are Not Exact
setTimeout(fn, 1000) means "run this after at least one second." It does not mean "run at exactly one second." If the main thread is busy, the callback is delayed.
The timer callback will not appear at 100 milliseconds. It will only run after the blocking loop finishes and the event loop can schedule it.
Microtasks and Rendering Also Matter
Promises add another queue often called the microtask queue. Microtasks usually run before the runtime takes the next timer callback, which is why promise chains can appear to "jump ahead" of timers.
Typical output is:
syncpromisetimeout
That ordering does not contradict single-threaded execution. It reflects queue priority rules inside the runtime.
Common Pitfalls
The biggest misconception is thinking setTimeout starts a new JavaScript thread. It does not. Another common mistake is assuming a timer delay is exact, when it only defines the earliest time the callback can be queued. Long synchronous work blocks timer callbacks, rendering, and user input alike. Developers also confuse runtime concurrency with parallel JavaScript execution. In browsers and Node.js, many things can be in flight at once, but the main JavaScript callback execution model is still one piece of code at a time on a given thread.
Summary
- JavaScript runs one main piece of code at a time on a single call stack.
- Timers are tracked by the host runtime, not by a separate JavaScript execution thread.
- When a timer expires, its callback is queued and runs later when the stack is free.
- A clock works by scheduling repeated callbacks with
setIntervalorsetTimeout. - Timer delays are minimum delays, not exact execution times.
- Promise microtasks can run before timer callbacks because of event loop rules.

