Hackforge Academy

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

πŸš€ Learn Spring Boot with real-world projects

πŸ’‘ Build REST APIs step by step

🧠 Improve backend development skills

🎯 Get career-ready practical training

Join Our Free WhatsApp Community

Direct access to niche-specific mentors and peers on WhatsApp.

🐍

Python Community

Discuss Django, FastAPI, AI integration, and automation scripts with 15k+ developers.

Join Python Community
βš›οΈ

React Community

Master Next.js, Framer Motion, and State Management. Share your latest UI components.

Join React Community
β˜•

Java Community

Deep dives into Spring Boot, Microservices architecture, and high-performance backend ops.

Join Java Community