In a microservices architecture, services often need to communicate with each other. While REST APIs are common, gRPC offers better performance, smaller payloads, and native code generation across languages. In this article, we’ll build two microservices in FastAPI that talk to each other using gRPC.
We will cover:
- How to define a gRPC contract using Protobuf
- How to implement a gRPC server in one FastAPI microservice
- How to consume that gRPC service in another FastAPI microservice
- How to run everything with Docker Compose
Requirements:
- Python version “3” installed on your computer.
- Docker and Docker compose installed on your computer.
Project Structure
This is the final project structure. Make sure to create all folders first.
grpc-fastapi-demo/
├── proto/
│ └── greeter.proto
├── greeter_service/
│ ├── main.py
│ ├── greeter_pb2.py
│ └── greeter_pb2_grpc.py
├── client_service/
│ ├── main.py
│ └── greeter_pb2.py ← same as in greeter_service
│ └── greeter_pb2_grpc.py ← same as in greeter_service
├── docker-compose.yml
├── requirements.txt
└── README.md
Step 1: Define the gRPC Contract with Protobuf
Create a file named “greeter.pro” in “proto” folder.
Put these contents in it:
syntax = "proto3";
package greeter;
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply);
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
Step 2: Install necessary libraries
The next step is to create proto files from “greeter.pro” file which we have created in the previous step.
To do this you need a Python library named “grpcio-tools”.
To install this library, you first need a Python virtual environment.
In the root of the project run this command:
python3 -m virtualenv venv
or
python -m virtualenv venv
If “virtualenv” not installed on your system, you need to first run this command:
pip3 install virtualenv
or
pip install virtualenv
Then activate virtualenv by using this command:
source venv/bin/activate
And then install the necessary library:
pip install grpcio-tools
Step 3: Create proto files
Now it’s time to create proto files from “greeter.pro”, run this command:
python -m grpc_tools.protoc -Iproto --python_out=greeter_service --grpc_python_out=greeter_service proto/greeter.proto
This will create proto files.
Then copy generated proto files into “client_service” folder:
cp greeter_service/greeter_pb2*.py client_service/
Step 4: Create “greeter_service”
Create a main.py file inside “greeter_service” folder and put these contents in it:
import grpc
from concurrent import futures
from greeter_pb2 import HelloReply
import greeter_pb2_grpc
class GreeterService(greeter_pb2_grpc.GreeterServicer):
def SayHello(self, request, context):
return HelloReply(message=f"Hello, {request.name}!")
def serve():
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
greeter_pb2_grpc.add_GreeterServicer_to_server(GreeterService(), server)
server.add_insecure_port("[::]:50051")
server.start()
print("Greeter server is running on port 50051...")
server.wait_for_termination()
if __name__ == "__main__":
serve()
As you can see this will create a GRPC server using Python.
Step 5: Create “client_service”
In the “client_service” folder create a file named “main.py” and put these contents in it:
from fastapi import FastAPI
import grpc
import greeter_pb2
import greeter_pb2_grpc
app = FastAPI()
@app.get("/greet/{name}")
async def greet(name: str):
channel = grpc.insecure_channel("greeter_service:50051")
stub = greeter_pb2_grpc.GreeterStub(channel)
response = stub.SayHello(greeter_pb2.HelloRequest(name=name))
return {"message": response.message}
As you can see in this file, we are creating a GRPC connection to “greeter_service” using the name of the container and the specified port.
Then we are calling SayHello function from “client_service” to “greeter_service”.
Step 6: Create Docker compose file
Create a docker compose file inside the root of the project, and put these contents in it:
services:
greeter_service:
build:
context: ./greeter_service
ports:
- "50051:50051"
networks:
- fastapi-grpc-microservices-network
client_service:
build:
context: ./client_service
ports:
- "8000:8000"
depends_on:
- greeter_service
networks:
- fastapi-grpc-microservices-network
networks:
fastapi-grpc-microservices-network:
driver: bridge
Step 7: Create Dockerfile for “greeter_service”:
In the “greeter_service” folder create a file named “Dockerfile” and put these contents in it:
FROM python:3.11
WORKDIR /app
COPY . .
RUN pip install --no-cache-dir -r requirements.txt
CMD ["python", "main.py"]
Step 8: Create Dockerfile for “client_service”
In the “client_service” folder create a file named “Dockerfile” and put these contents in it:
FROM python:3.11
WORKDIR /app
COPY . .
RUN pip install -r requirements.txt
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
Step 9: Create “requirements.txt” for “greeter_service”
In the “greeter_service” folder create a file named “requirements.txt” and put these contents in it:
grpcio
grpcio-tools
Step 10: Create “requirements.txt” for “client_service”:
In the “client_service” folder create a file named “requirements.txt” and put these contents in it:
fastapi
uvicorn
grpcio
grpcio-tools
Step 10: Final check
Now, you should have a folder structure like this:
grpc-fastapi-demo/
├── proto/
│ └── greeter.proto
├── greeter_service/
│ ├── main.py
│ ├── greeter_pb2.py
│ └── greeter_pb2_grpc.py
├── client_service/
│ ├── main.py
│ └── greeter_pb2.py ← same as in greeter_service
│ └── greeter_pb2_grpc.py ← same as in greeter_service
├── docker-compose.yml
├── requirements.txt
└── README.md
Step 11: Running the project
To run the project, open the terminal in the root of project and run this command:
docker compose up --build -d
Step 12: Testing the project
Open your web browser and enter this address:
http://localhost:8000/greet/Michael
This will show you something like this:

Which shows that the project is working fine.
Step 13: How it works
When you open the address in the browser, it is requesting to “client_service” which is a FastAPI app, and then FastAPI will create a GRPC connection to “greeter_service” and then “greeter_service” respond back using GRPC connection and then FastAPI returns the response to your browser.
The link of Github for this project is this:
Leave a Reply