Data Transmission
Synchronous Communication
Asynchronous Communication
Client-Server Architecture
Networking Basics

Synchronous and Asynchronous data transmission between client and server

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

Client-server communication can be implemented with synchronous or asynchronous flow, and the choice changes latency, throughput, and operational behavior. Synchronous communication waits for a response before continuing, while asynchronous communication allows work to continue and handles responses later. Good system design often mixes both styles based on endpoint requirements.

Core Sections

Synchronous Transmission Model

In synchronous request-response, a client sends a request and blocks until response or timeout. This pattern is simple, predictable, and easy to debug for short operations.

python
1# synchronous HTTP call with requests
2import requests
3
4resp = requests.get("https://httpbin.org/get", timeout=5)
5print(resp.status_code)
6print(resp.json()["url"])

Strengths:

  • simple control flow
  • straightforward error handling
  • easy transactional reasoning

Tradeoff is waiting time. If server is slow, client thread stays occupied.

Asynchronous Transmission Model

In asynchronous flow, request initiation and response handling are decoupled. The caller can continue processing while awaiting result events.

python
1# asynchronous HTTP calls with aiohttp
2import asyncio
3import aiohttp
4
5async def fetch(url: str) -> int:
6    async with aiohttp.ClientSession() as session:
7        async with session.get(url) as resp:
8            await resp.text()
9            return resp.status
10
11async def main():
12    tasks = [fetch("https://httpbin.org/delay/1") for _ in range(3)]
13    statuses = await asyncio.gather(*tasks)
14    print(statuses)
15
16asyncio.run(main())

Asynchronous style improves concurrency for I O heavy workloads.

Where Each Style Fits Best

Use synchronous transmission when:

  • operation is short and strongly sequential
  • strong consistency and immediate result are required
  • team needs low complexity implementation

Use asynchronous transmission when:

  • many concurrent requests must be in flight
  • response time variance is high
  • system can tolerate eventual completion patterns

Neither style is universally better. The right choice is workload dependent.

Client Experience and Server Load

Synchronous APIs can feel snappy for fast endpoints but degrade quickly under slow dependencies. Asynchronous patterns can preserve responsiveness by offloading long work.

A common architecture is accept request quickly and process in background queue.

javascript
1// Node style pseudo flow
2app.post('/jobs', async (req, res) => {
3  const jobId = await enqueueJob(req.body)
4  res.status(202).json({ jobId })
5})

Client polls status endpoint or listens for callback.

Delivery Patterns for Asynchronous Systems

Common async delivery strategies:

  • polling status endpoints
  • webhooks
  • websocket push
  • message brokers and consumers

Example poll loop:

python
1import time
2import requests
3
4job_id = "abc123"
5for _ in range(10):
6    r = requests.get(f"https://api.example.com/jobs/{job_id}", timeout=3)
7    data = r.json()
8    if data["state"] == "done":
9        print("result", data["result"])
10        break
11    time.sleep(1)

Polling is simple but adds repeated network calls. Webhooks reduce polling overhead but require reliable callback infrastructure.

Reliability and Failure Handling

Synchronous systems rely on timeout and retry control at call sites. Asynchronous systems add extra concerns:

  • idempotency keys
  • duplicate message handling
  • retry backoff
  • dead-letter queues

These mechanisms are crucial for resilience and data integrity.

Security and Observability

Both models need authentication, authorization, and transport security. Asynchronous systems also need trace propagation across queues and workers.

Add correlation ids in request and message metadata to trace end-to-end flow.

text
request-id: 8f2d1c...

Without tracing, asynchronous incidents are harder to diagnose.

Common Pitfalls

  • Choosing asynchronous design without operational tooling for retries and tracing.
  • Using synchronous calls inside high-concurrency services and exhausting worker threads.
  • Treating asynchronous processing as fire-and-forget without result tracking.
  • Ignoring idempotency and creating duplicate side effects on retries.
  • Applying one communication style everywhere instead of per endpoint needs.

Summary

  • Synchronous communication is simple and immediate but blocking.
  • Asynchronous communication improves concurrency for slow or long tasks.
  • System design should match latency, consistency, and throughput goals.
  • Reliable asynchronous systems need explicit retry, idempotency, and observability.
  • Most mature platforms combine both models rather than picking one exclusively.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.