# Protobuf Editions Design: Features

**Author:** [@haberman](https://github.com/haberman), [@fowles](https://github.com/fowles)

**Approved:** 2022-10-13

A proposal to use custom options as our way of defining and representing features.

## Background

The [Protobuf Editions](what-are-protobuf-editions.md) project uses "editions" to allow Protobuf to safely evolve over time. An edition is formally a set of "features" with a default value per feature. Features define the specific points of change and evolution on a per entity basis within a .proto file.

## Sample Usage

```
edition = "2023";

package experimental.users.kfm.editions;

import "net/proto2/proto/features_cpp.proto";

option features.repeated_field_encoding = EXPANDED;
option features.enum = OPEN;
option features.(pb.cpp).string_field_type = STRING;

message Lab {
  enum Mouse {
    UNKNOWN_MOUSE = 0;
    PINKY = 1;
    THE_BRAIN = 2;
  }
  repeated Mouse mice = 1 [features.repeated_field_encoding = PACKED];
  string name = 2;
  string address = 3 [features.(pb.cpp).string_field_type = CORD];
}
```

## Language-Specific Features

Extensions manage features specific to individual code generators:

```
message Features {
  ...
  extensions 1000;  // for features_cpp.proto
  extensions 1001;  // for features_java.proto
}
```

## Inheritance

Feature inheritance is exactly the behavior of `MergeFrom`:

```
void InheritFrom(const Features& parent, Features* child) {
  Features tmp(parent);
  tmp.MergeFrom(child);
  child->Swap(&tmp);
}
```

## Target Attributes

```
enum FeatureTargetType {
  FILE = 0;
  MESSAGE = 1;
  ENUM = 2;
  FIELD = 3;
  ...
};
```

## Retention

```
enum FeatureRetention {
  SOURCE = 0;
  RUNTIME = 1;
}
```

## Edition Zero Features

```
message Features {
  enum FieldPresence {
    EXPLICIT = 0;
    IMPLICIT = 1;
    LEGACY_REQUIRED = 2;
  }
  optional FieldPresence field_presence = 1 [
      retention = RUNTIME,
      target = FIELD,
      (edition_defaults) = { edition: "2023", default: "EXPLICIT" }
  ];

  enum EnumType {
    OPEN = 0;
    CLOSED = 1;
  }
  optional EnumType enum = 2 [
      retention = RUNTIME,
      target = ENUM,
      (edition_defaults) = { edition: "2023", default: "OPEN" }
  ];

  enum RepeatedFieldEncoding {
    PACKED = 0;
    EXPANDED = 1;
  }
  optional RepeatedFieldEncoding repeated_field_encoding = 3 [
      retention = RUNTIME,
      target = FIELD,
      (edition_defaults) = { edition: "2023", default: "PACKED" }
  ];

  enum MessageEncoding {
    LENGTH_PREFIXED = 0;
    DELIMITED = 1;
  }
  optional MessageEncoding message_encoding = 5 [
      retention = RUNTIME,
      target = FIELD,
      (edition_defaults) = { edition: "2023", default: "LENGTH_PREFIXED" }
  ];

  extensions 1000;  // for features_cpp.proto
  extensions 1001;  // for features_java.proto
}
```

---
Source: https://raw.githubusercontent.com/protocolbuffers/protobuf/main/docs/design/editions/protobuf-editions-design-features.md
Downloaded: 2026-06-07
