Protocol Buffers & gRPC Reference
Searchable proto3 syntax reference — messages, enums, services, scalar types, streaming patterns, and full real-world .proto files. Copy-paste ready.
Showing 12 of 12 syntax patterns
Message Definition
MessageMessages are the primary data container in proto3, equivalent to a struct or class.
syntax = "proto3";
message User {
string id = 1;
string name = 2;
string email = 3;
int32 age = 4;
bool is_active = 5;
}Enum
EnumEnums define a set of named constant values. The first value must be 0 in proto3.
enum UserRole {
USER_ROLE_UNSPECIFIED = 0;
USER_ROLE_ADMIN = 1;
USER_ROLE_EDITOR = 2;
USER_ROLE_VIEWER = 3;
}
message User {
string id = 1;
string name = 2;
UserRole role = 3;
}Service Definition
ServiceServices define the RPC methods that a server exposes to clients.
service UserService {
rpc GetUser (GetUserRequest) returns (User);
rpc CreateUser (CreateUserRequest) returns (User);
rpc UpdateUser (UpdateUserRequest) returns (User);
rpc DeleteUser (DeleteUserRequest) returns (DeleteUserResponse);
rpc ListUsers (ListUsersRequest) returns (ListUsersResponse);
}Unary RPC
ServiceClassic request-response pattern. Client sends one message, server responds with one message.
service GreetService {
// Unary: one request → one response
rpc SayHello (HelloRequest) returns (HelloResponse);
}
message HelloRequest {
string name = 1;
}
message HelloResponse {
string message = 1;
}Server Streaming RPC
ServiceClient sends one request, server returns a stream of responses.
service StockService {
// Server streaming: one request → stream of responses
rpc WatchPrice (WatchPriceRequest) returns (stream PriceUpdate);
}
message WatchPriceRequest {
string symbol = 1;
}
message PriceUpdate {
string symbol = 1;
double price = 2;
int64 timestamp = 3;
}Client Streaming RPC
ServiceClient sends a stream of requests, server responds once after all are received.
service UploadService {
// Client streaming: stream of requests → one response
rpc UploadFile (stream FileChunk) returns (UploadResponse);
}
message FileChunk {
bytes data = 1;
string filename = 2;
int32 chunk_index = 3;
}
message UploadResponse {
string file_id = 1;
int64 bytes_received = 2;
}Bidirectional Streaming RPC
ServiceBoth client and server send streams independently — full-duplex communication.
service ChatService {
// Bidirectional streaming: stream ↔ stream
rpc Chat (stream ChatMessage) returns (stream ChatMessage);
}
message ChatMessage {
string user_id = 1;
string text = 2;
int64 timestamp = 3;
}Field Rules — repeated & map
FieldsUse repeated for lists and map for key-value pairs. In proto3, all singular fields are optional by default.
message Order {
string id = 1;
// repeated = list/array
repeated string item_ids = 2;
repeated OrderItem items = 3;
// map = key-value pair
map<string, string> metadata = 4;
map<string, int32> quantities = 5;
}
message OrderItem {
string product_id = 1;
int32 quantity = 2;
double price = 3;
}oneof
Fieldsoneof ensures that only one of its fields is set at a time — useful for discriminated unions.
message Notification {
string user_id = 1;
string title = 2;
oneof payload {
EmailPayload email = 3;
PushPayload push = 4;
SmsPayload sms = 5;
}
}
message EmailPayload {
string to = 1;
string subject = 2;
string body = 3;
}
message PushPayload {
string device_token = 1;
string body = 2;
}reserved Fields
FieldsReserve field numbers and names to prevent future reuse after removing fields.
message User {
reserved 2, 15, 9 to 11;
reserved "foo", "bar";
string id = 1;
string name = 3;
string email = 4;
}import
OrganizationImport other proto files to reuse message types and services.
syntax = "proto3";
import "google/protobuf/timestamp.proto";
import "google/protobuf/empty.proto";
import "common/pagination.proto";
message Post {
string id = 1;
string title = 2;
google.protobuf.Timestamp created_at = 3;
}
service PostService {
rpc DeletePost (DeletePostRequest) returns (google.protobuf.Empty);
}package & options
OrganizationPackages namespace your types. Options configure language-specific code generation.
syntax = "proto3";
package com.example.user.v1;
option go_package = "github.com/example/user/v1;userv1";
option java_package = "com.example.user.v1";
option java_multiple_files = true;
option java_outer_classname = "UserProto";
message User {
string id = 1;
string name = 2;
}What are Protocol Buffers?
Protocol Buffers (Protobuf) is a binary serialization format developed by Google. You define the structure of your data once in a .proto file, then generate strongly-typed code for any supported language (Go, Python, Java, C++, TypeScript, Ruby, and more). The result is data that serializes 3–10x smaller than JSON and parses significantly faster.
Protobuf is the default serialization format for gRPC, but it can also be used independently as a storage or messaging format. Because schemas are defined explicitly, tooling can validate messages at compile time and generate documentation automatically.
Proto3 vs Proto2
Proto3 is the recommended version for all new projects. The major improvements over proto2 include:
- No required fields: All singular fields are optional by default, making schemas more forward-compatible.
- Fixed zero values: Unset fields default to their type's zero value (0, false, empty string) instead of requiring explicit defaults.
- Native JSON mapping: Proto3 defines a canonical JSON encoding, making debugging much easier.
- map fields: First-class map support without workarounds.
- Simpler syntax: Removed groups and other legacy features.
gRPC Service Types
gRPC is a high-performance RPC framework built on top of HTTP/2 and Protocol Buffers. It supports four communication patterns:
- Unary: Classic request-response, like a REST API call. Best for most CRUD operations.
- Server Streaming: Server sends multiple responses for one request. Ideal for live feeds, log tailing, and large result sets.
- Client Streaming: Client sends multiple messages, server responds once. Useful for file uploads or batched metric ingestion.
- Bidirectional Streaming: Full-duplex communication over a single long-lived connection. Perfect for real-time chat, collaborative editing, or game state synchronization.
FAQ
What are Protocol Buffers (Protobuf)?
Protocol Buffers (Protobuf) is a language-neutral, platform-neutral, extensible mechanism for serializing structured data, developed by Google. You define how you want your data to be structured in a .proto file, then use generated code to read and write that structured data. Protobuf serializes significantly smaller and faster than JSON or XML.
What is the difference between proto2 and proto3?
Proto3 is the current recommended version. Key differences: proto3 removes required fields (all fields are optional by default), eliminates field default values (each type has a fixed zero value), simplifies the syntax, and adds support for JSON serialization. Proto3 also introduced the map field type natively. Proto2 is still supported but new projects should use proto3.
What are the four types of gRPC service methods?
gRPC supports four communication patterns: (1) Unary RPC — client sends one request and receives one response, like a regular function call. (2) Server streaming — client sends one request and receives a stream of responses. (3) Client streaming — client sends a stream of requests and receives one response. (4) Bidirectional streaming — both client and server send independent streams of messages using the same connection.
How do I handle errors in gRPC?
gRPC uses a set of status codes instead of HTTP status codes. The most common are: OK (success), INVALID_ARGUMENT (bad input), NOT_FOUND (resource doesn't exist), ALREADY_EXISTS (resource conflict), PERMISSION_DENIED (no access), UNAUTHENTICATED (missing credentials), UNAVAILABLE (server not ready), and DEADLINE_EXCEEDED (timeout). On the server, return a status error; on the client, check the error code using status.FromError().
What field numbers can I use in a proto3 message?
Field numbers must be between 1 and 536,870,911. Numbers 1–15 take one byte to encode (use for frequently occurring fields). Numbers 16–2047 take two bytes. Numbers 19,000–19,999 are reserved for the protobuf implementation. Once you assign a field number and the schema is in production, never reuse it — even if you remove the field. Use the reserved keyword to prevent accidental reuse.