Category: python
Introduction to Service-to-Service Communication
Published on 22 Aug 2026
Explanation
In a microservices architecture, services need to communicate with each other to complete business operations. For example, an Order Service may need to contact a Product Service to verify product details before creating an order. Services commonly communicate using HTTP REST APIs, gRPC, or message brokers. In Python microservices, libraries such as httpx and requests can be used for HTTP communication. Each service should have a clear API contract and handle communication failures gracefully.
Code:
# Product Service
# product_service.py
from fastapi import FastAPI
app = FastAPI()
@app.get('/products/{product_id}')
def get_product(product_id: int):
return {
'id': product_id,
'name': 'Laptop',
'price': 65000
}
# Run Product Service on port 8001
# uvicorn product_service:app --port 8001
Explanation
The httpx library can be used by a FastAPI service to make HTTP requests to another service. It supports both synchronous and asynchronous communication. In an async FastAPI endpoint, httpx.AsyncClient is commonly used so that the application can perform network I/O without blocking the event loop. In this example, the Order Service calls the Product Service to retrieve product information.
Code:
# Install HTTPX
# pip install httpx
from fastapi import FastAPI
import httpx
app = FastAPI()
PRODUCT_SERVICE_URL = 'http://localhost:8001'
@app.get('/orders/product/{product_id}')
async def get_product(product_id: int):
async with httpx.AsyncClient() as client:
response = await client.get(
f'{PRODUCT_SERVICE_URL}/products/{product_id}'
)
return response.json()
# Run Order Service on port 8002
# uvicorn order_service:app --port 8002
Explanation
Network communication can fail because a service may be unavailable, slow, or return an error response. A microservice should not blindly trust another service to always be available. HTTPX provides exceptions such as RequestError for network failures. FastAPI's HTTPException can be used to return meaningful HTTP status codes such as 503 Service Unavailable. Timeouts should also be configured so that one unavailable service does not make the calling service wait indefinitely.
Code:
from fastapi import FastAPI, HTTPException
import httpx
app = FastAPI()
PRODUCT_SERVICE_URL = 'http://localhost:8001'
@app.get('/orders/product/{product_id}')
async def get_product(product_id: int):
try:
async with httpx.AsyncClient() as client:
response = await client.get(
f'{PRODUCT_SERVICE_URL}/products/{product_id}',
timeout=5.0
)
response.raise_for_status()
return response.json()
except httpx.HTTPStatusError:
raise HTTPException(
status_code=502,
detail='Product Service returned an error'
)
except httpx.RequestError:
raise HTTPException(
status_code=503,
detail='Product Service is unavailable'
)
Explanation
Microservices can exchange data using HTTP request bodies. A POST request can send JSON data from one service to another. FastAPI uses Pydantic models to validate incoming request data. For example, the Order Service can send product ID, quantity, and customer ID to another service. Using structured request and response models makes communication between services more predictable and easier to maintain.
Code:
from fastapi import FastAPI
from pydantic import BaseModel
import httpx
app = FastAPI()
class OrderRequest(BaseModel):
customer_id: int
product_id: int
quantity: int
@app.post('/orders')
async def create_order(order: OrderRequest):
async with httpx.AsyncClient() as client:
response = await client.post(
'http://localhost:8001/orders',
json=order.model_dump(),
timeout=5.0
)
return {
'message': 'Order request sent',
'response': response.json()
}
Explanation
A real-world e-commerce application may contain several independent services. An API Gateway receives requests from clients and routes them to services such as User, Product, Order, and Payment. The Order Service may communicate with Product and Payment Services to complete an order. As the system grows, additional patterns such as service discovery, API gateways, authentication, retries, circuit breakers, distributed tracing, and message queues can be introduced. These patterns help make communication reliable in large microservices systems.
Code:
# Client # | # v # API Gateway # | # +----------> User Service # | # +----------> Product Service # | # +----------> Order Service # | # +----> Product Service # | # +----> Payment Service # # Typical communication: # Client -> API Gateway -> Order Service # Order Service -> Product Service # Order Service -> Payment Service