In software development, there are two important concepts: synchronous and asynchronous behavior. JavaScript developers, especially those who use vanilla JavaScript, know these well because of how promises work.
I like to explain things in a simple way, so it’s easier for me and others to understand new topics.
Synchronous Programming
Let’s imagine you went to a restaurant:
You ask the server for the menu,
You sit at the table and wait for the menu,
The menu arrives,
You choose your order,
The server takes your order,
The server tells the chef to prepare it,
The chef finishes the order,
You receive your meal,
You eat, pay, and leave the restaurant.
In this scenario, everything happens in sequence. So you can’t move to the next step until the current step is finished. This is called synchronous programming.
Check this simple illustration to understand it better:

Asynchronous Programming
Now, let’s imagine another situation:
You send an email to your teammate,
While waiting for their response, you continue with other tasks,
Your teammate receives the email,
He handle your request,
In the meanwhile, you’ve already completed many tasks,
Finally, you receive their response.
Here, each step happens independently. You don’t have to wait for a response to continue working. This is called asynchronous programming.
Check the illustration below for simple explanation:

Synchronous Code Example in PHP:
<?php
// this is an example of syncronous code with code blocking so that the next line
// will not be executed until the file is read
// Enable error reporting for debugging
error_reporting(E_ALL);
ini_set('display_errors', 1);
echo "Sync example\n";
$filename = "file.txt";
$file = fopen($filename, "r");
$content = fread($file, filesize($filename));
echo $content;
fclose($file);
echo "\nend \n";
Asynchronous Code Example in PHP:
<?php
// This is an example of asynchronous code that demonstrates non-blocking operations
// It will read the file line by line while performing other tasks
// Enable error reporting for debugging
error_reporting(E_ALL);
ini_set('display_errors', 1);
echo "Starting async example...\n";
$filename = "file.txt";
$file = fopen($filename, "r");
echo "perform initial task\n";
usleep(2000);
while (!feof($file)) {
echo fgets($file) . "\n";
usleep(2000);
echo "perform other task\n";
usleep(2000);
}
// but not for complex operations you will need to use queues and threads
When to use Sync Operations:
Simple and sequential tasks, when you have number of tasks that must be executed one after the other, and the order of execution is important.
Examples:
- Reading a file, processing the data, and displaying the results in a simple application or component.
- When simplicity is the key: For small scripts or programs where performance is not a critical concern, synchronous code can be easier to write, read, and debug.
- When additional CPU costs not needed to perform multi-tasking operations.
When to Use Async Operations:
I/O-Bound Operations: when your program spends significant time waiting for external resources like;
- Network requests: Fetching data from APIs or databases.
- File system operations: Reading or writing big files.
- User input/output: Waiting for user interaction based on their internet speed
- Multi Tasks: When you need to handle multiple tasks simultaneously without blocking the main program’s execution examle of sending emails to multiple users, processing multiple requests concurrently in a web server.
- Improving Responsiveness: Making your application more responsive to user input, even while performing long-running operations.
Sending example is a perfect use case for asynchronous programming. By using async operations, we can improve UX and allow users to continue using the application while emails are being sent in the background.