Proto2 vs Proto3: Key Differences

Compare proto2 and proto3 syntax differences including required/optional fields, default values, enums, extensions, and migration strategies between versions.

Advanced Features

Detailed Explanation

Proto2 vs Proto3 Comparison

Proto3 simplified the protobuf language by removing several proto2 features and changing default behaviors. Understanding the differences is essential when working with legacy schemas or migrating between versions.

// Proto2 syntax
syntax = "proto2";

message UserV2 {
  required int32 id = 1;
  required string name = 2;
  optional string email = 3;
  optional int32 age = 4 [default = 0];
  repeated string tags = 5;

  extensions 100 to 199;
}

// Proto3 syntax
// syntax = "proto3";
//
// message UserV3 {
//   int32 id = 1;
//   string name = 2;
//   string email = 3;
//   optional int32 age = 4;
//   repeated string tags = 5;
// }

Feature Comparison

Feature Proto2 Proto3
Field presence required, optional, implicit Implicit (all optional), explicit optional keyword
Default values Custom defaults allowed Fixed defaults only (0, false, "")
required keyword Supported Removed (considered harmful)
Unknown fields Discarded by default Preserved by default
Enum zero value Not required Must have zero value
Extensions Supported Removed (use Any instead)
Groups Supported (deprecated) Removed
Map fields Not available Added
JSON mapping Basic Full standard mapping

Why required Was Removed

The required keyword in proto2 was identified as the largest source of backward-compatibility bugs. Once a field is marked required, it can never be removed without breaking all existing parsers. Proto3 treats all fields as optional, making schema evolution safer.

Field Presence in Proto3

In proto3, scalar fields do not track whether they were explicitly set. A field with value 0 could be "set to zero" or "not set at all." To distinguish these cases:

  • Use wrapper types (google.protobuf.Int32Value)
  • Use the optional keyword (added back in proto3.15+)
  • Use a boolean companion field (e.g., bool has_age = 5;)

Migration Strategy

When migrating from proto2 to proto3:

  1. Remove all required labels
  2. Remove custom default values
  3. Remove extensions (replace with google.protobuf.Any or oneof)
  4. Ensure all enums have a zero value
  5. Test with existing serialized data to verify compatibility

Use Case

Deciding which protobuf version to use for a new project, migrating legacy proto2 schemas to proto3, or understanding why a codebase uses specific protobuf patterns dictated by the version.

Try It — Protobuf Definition Parser

Open full tool