Docs That Write Themselves: Scaling With gRPC and Protobuf
Use .proto files as the single source of truth. Generate both documentation and service stubs from them. Move all contracts — including Kafka events — to gRPC.
Join the DZone community and get the full member experience.
Join For FreeIn this article, we’ll explore how gRPC and code generation can help you:
- Write documentation that people actually read and use,
- Standardize communication between microservices,
- Avoid code duplication across services.
Nowadays, many developers are already familiar with gRPC. It’s no longer surprising that service-related teams prefer it for inter-service communication and even for documentation purposes.
Let’s start with the key idea: Define interfaces and data structures in one place — .proto
files — and auto-generate everything else.
How to Write Technical Documentation That Gets Read
It’s a tough challenge, no matter your process. A few edits to the code, and the docs are already outdated. So, what can we do?
Common Problems
- Documentation becomes outdated faster than the code.
- It’s hard to find the correct contract.
- There’s no single format: some use Confluence, some use README files, and others write nothing.
But what if .proto
files could solve this? What if we wrote code that documents itself? Let’s say we create a /post-context
directory with the following:
// common/message.proto
syntax = "proto3";
package common;
// User-generated content (post) object
message Post {
string id = 1; // Unique ID
string title = 2; // Title
string content = 3; // Body
repeated string tags = 4;// Tags
}
Then what? Let’s just run code generation and generate docs directly from CI/CD:
protoc \
-I. \
--doc_out=markdown,docs.md:./docs \
api/common/*.proto api/post/**/*.proto
And that's all.
Key Takeaways
- Use
.proto
as the single source of truth. - Add meaningful comments to every message and RPC.
- Use tools like
protoc-gen-doc
,grpc-gateway
, or Swagger/OpenAPI to generate documentation automatically.
This results in up-to-date, readable, and auto-maintained documentation.
How to Standardize Service Communication
Let’s say you now have lots of contexts and directories. How do you ensure everything follows a standard?
Current Issues
- One service uses JSON, another XML, and another gRPC.
- The same object (e.g., Post) is described differently in each place.
- Adding new services is painful.
What if we move everything possible into gRPC — even Kafka messages?
Our Approach
- Define Kafka event
PostCreatedEvent
incommon/event.proto
. - Just import what you need:
import "common/message.proto";
import "common/event.proto";
Sure, duplication happens. Especially when teams move fast — enums, error codes, and more may get copied around. And then one tiny change causes a cascade of manual updates.
Let's follow the structure:
api
├── common
│ ├── message.proto # Post object
│ └── event.proto # PostCreatedEvent for Kafka
├── post
│ ├── post-service
│ │ ├── messages.proto # Specific DTOs
│ │ └── service.proto # CreatePost method
│ └── posts-admin
│ ├── messages.proto
│ └── service.proto # GetPost, UpdatePost methods
└── content
└── event-service
├── messages.proto # Empty DTO
└── service.proto # Empty service
Example: Using a shared Post
object.
// post-service/service.proto
syntax = "proto3";
package post;
import "common/message.proto";
service PostService {
rpc CreatePost (common.Post) returns (CreatePostResponse);
}
message CreatePostResponse {
string id = 1;
}
And service layer:
// posts-admin/service.proto
syntax = "proto3";
package admin;
import "common/message.proto";
service PostsAdminService {
rpc GetPost (GetPostRequest) returns (common.Post);
rpc UpdatePost (common.Post) returns (UpdatePostResponse);
}
message GetPostRequest {
string id = 1;
}
message UpdatePostResponse {
bool success = 1;
}
Problems Solved
- All communication goes through gRPC.
- All contracts are defined in
.proto
files insideapi/
. - Reusable types (DTOs, events) are kept in
api/common/
. - duplicates objects do not exist
If you plug this into a shared CI/CD pipeline — congratulations, you’ve got full automation!
Conclusion
Let me say this confidently:
gRPC + Protobuf + Codegen = readable, scalable, and fast development.
Key Takeaways
- Docs get read — because they’re auto-generated from a single, up-to-date source.
- Communication is standardized — because gRPC enforces strict contracts.
- Code duplication is minimized — thanks to shared types and event definitions.
Don’t be afraid to standardize and optimize your specs.
Hopefully, this article helped you see how protoc
and gRPC can solve real-world issues with documentation and integration.
Good luck out there!
Opinions expressed by DZone contributors are their own.
Comments