If you've ever wondered how different parts of an app talk to each other β or how microservices "call" each other behind the scenes β this one's for you.
In this post, I'll show you how to use gRPC in Python to build a menu service. We'll keep things light, use a kitchen/waiter analogy π½οΈ, and write some real working code together.
π What's gRPC? (But Make It Restaurant-Themed)
Let's say you're at a restaurant:
- Kitchen = the server (makes food)
 - Waiter = the client (asks for food)
 - Menu = the data structure (what's available)
 
The waiter goes, "Hey, what's on the menu today?"
The kitchen replies with delicious dishes.
This is literally what gRPC helps services do: ask for stuff, get a response β but way faster and stricter than REST.
π οΈ Prerequisites
First, let's install what we need:
pip install grpcio grpcio-tools
  
  
  π Step 1: Define the Language (menu.proto)
We need a shared language both waiter and kitchen understand.
Create a file called menu.proto:
syntax = "proto3";
package menu;
import "google/protobuf/empty.proto";
service MenuService {
  rpc ListMenus (google.protobuf.Empty) returns (MenuList);
}
message Menu {
  string id = 1;
  string name = 2;
  string description = 3;
  double price = 4;
}
message MenuList {
  repeated Menu items = 1;
}
βοΈ Step 2: Generate Python Code from the Proto
This turns your .proto file into real Python code.
Run this in terminal:
python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. menu.proto
Boom π₯ β now you've got menu_pb2.py and menu_pb2_grpc.py.
π§βπ³ Step 3: Build the Server (Our Kitchen)
Create server.py:
import grpc
from concurrent import futures
from google.protobuf.empty_pb2 import Empty
import menu_pb2
import menu_pb2_grpc
class MenuService(menu_pb2_grpc.MenuServiceServicer):
    def ListMenus(self, request, context):
        return menu_pb2.MenuList(items=[
            menu_pb2.Menu(
                id="1", 
                name="Pizza Margherita", 
                description="Fresh tomatoes, mozzarella, basil", 
                price=12.99
            ),
            menu_pb2.Menu(
                id="2", 
                name="Classic Burger", 
                description="Beef patty, lettuce, tomato, cheese", 
                price=9.99
            ),
            menu_pb2.Menu(
                id="3", 
                name="Caesar Salad", 
                description="Crispy romaine, parmesan, croutons", 
                price=8.50
            ),
        ])
def serve():
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    menu_pb2_grpc.add_MenuServiceServicer_to_server(MenuService(), server)
    server.add_insecure_port("[::]:50051")
    server.start()
    print("π½οΈ gRPC Server running on port 50051")
    server.wait_for_termination()
if __name__ == "__main__":
    serve()
π§Ύ Step 4: Create the Client (Our Waiter)
Create client.py:
import grpc
from google.protobuf.empty_pb2 import Empty
import menu_pb2
import menu_pb2_grpc
def run():
    with grpc.insecure_channel("localhost:50051") as channel:
        stub = menu_pb2_grpc.MenuServiceStub(channel)
        try:
            response = stub.ListMenus(Empty())
            print("π Today's Menu:")
            print("-" * 40)
            for item in response.items:
                print(f"π½οΈ  {item.name}")
                print(f"    {item.description}")
                print(f"    π° ${item.price:.2f}")
                print()
        except grpc.RpcError as e:
            print(f"β Error: {e}")
if __name__ == "__main__":
    run()
π§ͺ Step 5: Try It Out
- Run the server (in one terminal):
 
   python server.py
- Run the client (in another terminal):
 
   python client.py
You should see something like:
π Today's Menu:
----------------------------------------
π½οΈ  Pizza Margherita
    Fresh tomatoes, mozzarella, basil
    π° $12.99
π½οΈ  Classic Burger
    Beef patty, lettuce, tomato, cheese
    π° $9.99
π½οΈ  Caesar Salad
    Crispy romaine, parmesan, croutons
    π° $8.50
Yesss π it's working!
π§ What's Actually Happening?
+-----------+        ask for menu       +-----------+
|  Client   |  ---------------------->  |  Server   |
| (Waiter)  |                          | (Kitchen) |
|           |  <----------------------  |           |
|           |      send back menu      |           |
+-----------+                          +-----------+
The waiter (client) asks for the menu using a specific method call. The kitchen (server) replies with a structured list of menu items. No JSON parsing, no HTTP overhead β just pure, efficient communication.
π€ Why Use gRPC Instead of REST?
| Feature | REST | gRPC | 
|---|---|---|
| Format | JSON (text) | Protocol Buffers (binary) | 
| Speed | Good | β‘ Faster! | 
| Type Safety | Runtime errors | Compile-time checks π‘οΈ | 
| Streaming | Limited | Bidirectional streams π | 
| Tooling | Manual setup | Auto-generated stubs πͺ | 
| Best For | Public APIs, web | Microservices, internal | 
π Level Up: Add Error Handling
Want to make it production-ready? Here's how to add proper error handling to your server:
def ListMenus(self, request, context):
    try:
        # Simulate potential database call
        menus = self._get_menus_from_database()
        return menu_pb2.MenuList(items=menus)
    except Exception as e:
        context.set_code(grpc.StatusCode.INTERNAL)
        context.set_details(f"Failed to fetch menus: {str(e)}")
        return menu_pb2.MenuList()
def _get_menus_from_database(self):
    # Your database logic here
    return [
        menu_pb2.Menu(id="1", name="Pizza", description="Yummy", price=12.99)
    ]
π‘ Quick Wins & Tips
File Structure:
your-project/
βββ menu.proto
βββ server.py
βββ client.py
βββ menu_pb2.py (generated)
βββ menu_pb2_grpc.py (generated)
Pro Tips:
- Always use 
with grpc.insecure_channel()for proper connection cleanup - Add proper logging with Python's 
loggingmodule - Use virtual environments: 
python -m venv grpc-env - For production, use secure channels with TLS
 
π― What's Next?
Now that you've got the basics down, here are some fun directions to explore:
- Add CRUD operations (Create, Update, Delete menu items)
 - Connect to a real database (PostgreSQL, MongoDB)
 - Add authentication with JWT tokens
 - Implement streaming for real-time updates
 - Deploy with Docker for easy distribution
 
π¬ Wanna Go Deeper?
Let me know in the comments if you want tutorials on:
- π Securing gRPC APIs with authentication
 - π gRPC + PostgreSQL integration
 - π Streaming with gRPC (real-time data)
 - π³ Dockerizing gRPC services
 - π gRPC + REST gateway (best of both worlds)
 
π Got Questions?
Drop them below β I love helping fellow devs learn backend stuff! Or tag me if you build something cool with gRPC!
Found this helpful? Give it a β€οΈ and follow for more beginner-friendly backend tutorials π
Happy coding! π
    
Top comments (0)