Synchronous
A communication model where the caller waits for the operation to complete before moving on. Simpler to reason about but blocks the thread.
What is Synchronous?
In short
Synchronous means the code that makes a call stops and waits until that call finishes and returns a result before running the next line. The caller is blocked for the whole duration of the operation, so the result is available immediately after, but nothing else runs on that thread in the meantime.
What synchronous actually means
In a synchronous model, operations happen one after another in a strict order. When your code calls a function, the program holds at that line until the function returns. The next statement does not run a microsecond early. This is the default way most people first learn to write code: read a file, then print its contents, then exit.
The defining property is blocking. The thread that made the call cannot do anything else while it waits. If you call a database query that takes 40 milliseconds, that thread sits idle for those 40 milliseconds and only continues once the rows come back.
Synchronous is about ordering and waiting, not about speed. A synchronous call can be fast (reading from memory in nanoseconds) or slow (a network request to another continent taking 300 milliseconds). What makes it synchronous is that the caller does not move on until it has the answer.
How it works under the hood
When a function is called synchronously, the runtime pushes a frame onto the call stack with the arguments and a return address. The function runs to completion, places its return value where the caller expects it, and pops its frame off the stack. Control flows straight back to the line after the call. This is the normal call-and-return mechanism every CPU and language supports natively.
For an operation that involves waiting, such as disk or network I/O, a blocking synchronous call typically asks the operating system for the data and then puts the thread to sleep. The OS scheduler parks that thread and gives the CPU to other threads. When the data arrives, the OS marks the thread runnable again and it picks up right where it left off. The CPU is not wasted, but that specific thread is stuck until the result is ready.
This is why synchronous I/O scales by adding threads. A classic synchronous web server like Apache with the prefork module dedicates one process or thread per connection. If 200 requests are each waiting on a slow database, you need at least 200 threads, and each thread costs memory (often 1 to 8 MB of stack). Asynchronous servers exist precisely to avoid that one-thread-per-wait cost.
When to use it and the trade-offs
Reach for synchronous code first because it is far easier to read, write, and debug. The execution order matches the source order top to bottom. Stack traces point straight at the failing line. There are no callbacks, promises, or event loops to reason about, and errors propagate cleanly with normal try and catch.
The cost is throughput under concurrency. A thread blocked on a synchronous call does no useful work while it waits, so handling many slow operations at once means holding many threads, which burns memory and hits context-switching limits. If you make ten independent API calls one after another and each takes 100 milliseconds, the total is 1000 milliseconds, whereas issuing them concurrently could finish in roughly 100.
A good rule: use synchronous for CPU-bound work, short local operations, scripts, and any logic where the next step genuinely needs the previous result. Switch to asynchronous or concurrent patterns for I/O-bound work at scale, such as a server fielding thousands of simultaneous requests that each wait on a network or database.
A concrete example
Picture a checkout endpoint that charges a card, writes an order row, and sends a confirmation email, in that order, synchronously. Charging the card takes 250 milliseconds, the database write 15 milliseconds, and the email send 400 milliseconds. The user stares at a spinner for about 665 milliseconds because each step waits for the one before it, even though the email has nothing to do with whether the page can load.
The fix is not always to make everything asynchronous. Keep the parts that must be ordered synchronous: you cannot write the order before the charge succeeds, and you should not confirm a charge that failed. But the email does not need to block the response. Many systems hand the email off to a background queue and return to the user as soon as the order is saved, cutting the perceived wait to about 265 milliseconds.
That pattern, synchronous where ordering and correctness demand it and asynchronous where the caller does not need the result, is how most production systems are actually built. Synchronous is not the slow choice or the wrong choice; it is the simple, correct default that you deviate from deliberately when waiting becomes the bottleneck.
Where it is used in production
Apache HTTP Server (prefork)
Classic synchronous, blocking model that dedicates one process or thread per connection, which is why it needs many workers to handle concurrent slow requests.
PostgreSQL client queries
A standard SQL query call blocks the calling thread until the database returns rows, the everyday synchronous request-response pattern.
gRPC unary calls
A blocking unary RPC sends a request and waits for the single response before continuing, the synchronous counterpart to streaming RPCs.
Stripe Payments API
A charge request is made synchronously so the server has a definitive success or failure before it confirms an order to the user.
Frequently asked questions
- What is the difference between synchronous and asynchronous?
- Synchronous means the caller waits for the operation to finish before moving on, so the result is available right after the call. Asynchronous means the caller starts the operation and continues immediately, getting the result later through a callback, promise, or event. Synchronous is simpler to reason about; asynchronous handles many waiting operations without blocking a thread for each one.
- Does synchronous mean slow?
- No. Synchronous describes the ordering and waiting behavior, not the speed. A synchronous call to memory can finish in nanoseconds. It only feels slow when it blocks on something slow, like a network request, because the thread cannot do anything else while it waits.
- Is synchronous the same as single-threaded?
- No. Synchronous refers to waiting for a call to return; single-threaded refers to having one thread of execution. You can run synchronous code across many threads, and a single-threaded program like Node.js relies heavily on asynchronous calls. They are independent ideas that often get confused.
- Why do synchronous servers need so many threads?
- Because a thread blocked on a synchronous I/O call cannot serve any other request while it waits. To handle 500 concurrent slow requests you need around 500 threads, each consuming memory for its stack. Asynchronous servers avoid this by letting one thread juggle many waiting operations.
- When should I prefer synchronous code?
- Use it for CPU-bound work, short local operations, scripts, and any step that genuinely needs the previous result before it can proceed. It is the simplest and most readable default. Move to asynchronous patterns when you have many I/O-bound operations running at once and blocking a thread per wait becomes the bottleneck.
Learn Synchronous hands-on
This page explains the idea. The full lesson lets you step through the ring as servers join and leave, read the implementation, and check yourself with a quiz. It is one of 760+ lessons in the System Design Masterclass, from your first API call to distributed consensus. Eleven Foundation lessons are free, no signup. Lifetime access is ₹499 in India or $7.99 worldwide, one payment, no subscription.
Related lessons
Lessons that touch on Synchronous as part of a larger topic.
Synchronous Replication
Wait for replicas to confirm before acknowledging writes, zero data loss at the cost of latency
intermediate · data replication distribution
Request-Response Pattern
The most fundamental messaging pattern, send a request, wait for a reply
intermediate · messaging event systems
Synchronous Processing
Sequential request-response pattern where each operation waits for the previous one
foundation · core fundamentals
Asynchronous Processing
Non-blocking concurrent operations that don't wait for each other
foundation · core fundamentals
Asynchronous Replication
The default replication mode, fast writes at the cost of potential data loss
intermediate · data replication distribution
See also
Related glossary terms you might want to look up next.
Asynchronous
A communication model where the caller fires off a request and continues without waiting for a response. Essential for non-blocking I/O and event-driven systems.
Latency
The time delay between sending a request and getting a response. Amazon found every 100ms of extra latency costs 1% in sales.
Throughput
The number of operations a system can handle per unit of time. Think of it as how many cars a highway can move per hour.
Bandwidth
The maximum amount of data that can be transferred over a network in a given time. It's the width of the pipe, not how fast the water flows.
TCP
A reliable transport protocol that guarantees data arrives in order and without errors. It uses a three-way handshake to establish connections.
HTTP
The protocol powering the web. A request-response model where clients ask for resources and servers respond. Stateless by design.