After two years of development, we're proud to announce that Protovalidate has reached v1.0.
Protovalidate is the semantic validation library for Protobuf. Protobuf gives you the structure of your data, but Protovalidate ensures the quality of your data. Without semantic validation, you're stuck writing the same validation logic over and over again across every service that consumes your messages. With Protovalidate, you define your validation rules once, directly on your schemas, and they're enforced everywhere.
We take stability seriously here at Buf: v1.0 is a commitment that Protovalidate will not break you. Not only are we committing to project stability moving forward, but we’re also confident that it is ready for all of your production workloads. In fact, companies as diverse as Microsoft, F5, GitLab, CoreWeave, Eurostar, ANZ, Bayer, Nike, and Cerbos already trust Protovalidate, and we hope that its v1.0 status will give them even more confidence. Protovalidate is available in Go, Java, Python, C++, and TypeScript. Head over to protovalidate.com to get started.
Protovalidate provides standard annotations to validate common rules on messages and fields, as well as the ability to use CEL to write custom rules. Here's what this looks like in practice:
import "buf/validate/validate.proto";
message User {
string id = 1 [(buf.validate.field).string.uuid = true];
uint32 age = 2 [(buf.validate.field).uint32.lte = 150];
string email = 3 [(buf.validate.field).string.email = true];
string first_name = 4 [(buf.validate.field).string.max_len = 64];
string last_name = 5 [(buf.validate.field).string.max_len = 64];
option (buf.validate.message).cel = {
id: "first_name_requires_last_name"
message: "last_name must be present if first_name is present"
expression: "!has(this.first_name) || has(this.last_name)"
};
}
This User message doesn't just define the shape of your data — it enforces that id
is a valid UUID, age
is reasonable, email
is properly formatted, and names aren't absurdly long. The CEL expression ensures that if you provide a first name, you must also provide a last name. These aren't just nice-to-haves; they're guarantees.
The story of Protovalidate begins with protoc-gen-validate (PGV), originally developed at Lyft and maintained by the Envoy project. PGV pioneered the concept of declarative validation for Protobuf, and gained significant adoption across the industry. However, as Protobuf ecosystems evolved and new requirements emerged, PGV's architecture began to show its age.
When the Envoy project approached us about taking over maintenance of PGV, we saw an opportunity to do more than just maintain the status quo. We'd been hearing from users about pain points: the difficulty of writing custom validation rules, the challenge of maintaining validation code generators for multiple languages, and the desire for more expressive validation semantics.
Rather than bolt on features to PGV, we designed Protovalidate from the ground up to address these challenges. By building on CEL, we eliminated the need for custom code generation for validation logic. By designing a new annotation structure, we made rules more intuitive and composable. Working with the teams behind each language's CEL implementation, Protovalidate ensures consistent validation everywhere — your rules work the same in Go as they do in TypeScript, Python, Java, and C++.
The response to Protovalidate has exceeded our expectations. Major organizations have widely integrated it into their production systems, validating billions of messages daily.
What's driving this adoption? It comes down to a simple value proposition: bad data is expensive. Every engineer has war stories about production incidents caused by malformed data making its way through systems. A missing required field here, an out-of-bounds value there, and suddenly your dashboards are wrong, your models are corrupted, or worse, your systems are down.
Protovalidate catches data quality issues at the source. When validation rules live with your schemas, they're impossible to forget or misconfigure. When validation happens automatically in your RPC framework or message queue, bad data never propagates. The result is systems you can trust.
V1.0 is a beginning, not an end. We're committed to Protovalidate's stability, but that doesn't mean we're done innovating. Here's what's on the horizon:
First, deeper framework integration. Protovalidate already works seamlessly with Connect, gRPC, and Bufstream. We're working to make integration even smoother, with native support in more RPC frameworks and message queues.
Second, richer validation semantics. While Protovalidate already supports sophisticated validation through CEL and a rich set of standard rules, we're exploring additional standardized rules for common patterns like phone numbers with country codes and domain-specific identifiers.
Third, better tooling. The Protovalidate playground already lets you test validation rules interactively. We're expanding this with IDE integration and comprehensive rule libraries.
Most importantly, we're building toward a world where Protovalidate is just one part of a comprehensive approach to data quality. Combined with the Buf Schema Registry for governance, Bufstream for broker-side validation, and the rest of the Buf ecosystem, Protovalidate helps ensure that your data is not just well-structured, but correct.
Protovalidate is more than a validation library — it's a commitment to data quality, enforced by the schema language itself.
Ready to get started? Check out our quickstart guides for Go, Java, Python, C++, and TypeScript. For those migrating from protoc-gen-validate, we've prepared a comprehensive migration guide.
Welcome to Protovalidate v1.0. Your data will thank you.