Risks with google/any.proto

Our platform supports google.protobuf/any.proto and while it works great, it has an extremely high likelihood of causing conflicts if it plays a significant part in your message building strategy.

Example

Assuming you have the following protobuf schema:

type Message {
  string message_id = 1;
  google.Any data = 2;
}

Assuming two events are emitted that have data set to the following types:

type BillingDetails {
  int id = 1;
}
type SignupDetails {
  string id = 1;
}

After decode of the Message, you get a schema conflict:

// Decoded BillingDetails
{
  "message_id": "foo",
  "data": {
    "id": 123
  }
}
// Decoded SignupDetails
{
  "message_id": "foo",
  "data": {
    "id": "bar"
  }
}

Meaning, because both BillingDetails and SignupDetails are assigned to the data field, the structure of data will be different between events. This will cause conflicts in any system that tries to index the data.

Solution

Use oneof.

The result will be longer but it will be:

  • Explicit - whoever is working with your protobuf schemas knows exactly what can be injected into the message

  • Has no chance for conflicts

This is what it would look like if the previous examples were oneof:

type Message {
  string message_id = 1;
  
  oneof details {
    BillingDetails billing = 2;
    SignupDetails signup = 3;
}

If this was decoded - you will have this:

// Decoded SignupDetails
{
  "message_id": "foo",
    "details": {
      "billing": {
        "id": "bar"
   }
  }
}
// Decoded BillingDetails
{
  "message_id": "foo",
  "details": {
    "signup": {
      "id": 123
    }
  }
}

This presents no conflicts because both “BillingDetails” and “SignupDetails” are stored in their own object and do not collide with any existing keys.

Last updated