Our system consists of multiple microservices that emit and consume events encoded in avro format (see schema at the bottom). A particular use case is the following: Service A emits an event (of type InvoiceEvents) on topic T1 and Services B and C (different dev teams) are consuming from T1. E.g. Service B is part of the Tax team, while Service C is part of the Product Fulfilment team.
I was expecting the following to be true (but it seems not to be):
- The schema could evolve from version 1 (v1) to version 2 (v2) by adding a new union type (i.e. InvoiceCreated for field "payload") - Check out sample schemas at the bottom.
- The producing Service A to upgrade to v2 (i.e. producing events that follow v2)
- Some consuming services (e.g. Service C) could still use v1, as they are not interested in the new event type (i.e. InvoiceCreated). In this case, the "payload" field will use the default (null) value when de-serialised.
- Eventually and only if required for business reasons service C can upgrade to use v2, if there is a requirement to react on the new event type (i.e. InvoiceCreated).
But Service C cannot de-serialize new events of type InvoiceCreated. Specifically it is throwing:
org.apache.avro.AvroTypeException: Found com.elsevier.q2c.schema.avro.invoice.InvoiceCreated, expecting unionorg.apache.avro.AvroTypeException: Found com.elsevier.q2c.schema.avro.invoice.InvoiceCreated, expecting union at org.apache.avro.io.ResolvingDecoder.doAction(ResolvingDecoder.java:292) at
Are avro union types not forward compatible (as described above)? Are they only backwards compatible as implied by the Confluent Schema Registry tests. What is the proposed way to avoid the coupling of microservices? I guess avro unions cannot be used..
Thanks!!
Related link with no definite answer: Avro-union-compatibility-mode-enhancement-proposal
schema v1:
[
...
{
"type":"record",
"name":"InvoiceEvents",
"namespace":"bla.bla.schema.avro.invoice",
"fields":[
{
"name":"payload",
"type":[
"null",
"bla.bla.schema.avro.invoice.InvoiceDrafted"
],
"default":null
}
]
}
]
schema v2 (added new Union type: InvoiceCreated):
[
...
{
"type":"record",
"name":"InvoiceEvents",
"namespace":"bla.bla.schema.avro.invoice",
"fields":[
{
"name":"payload",
"type":[
"null",
"bla.bla.schema.avro.invoice.InvoiceDrafted",
"bla.bla.schema.avro.invoice.InvoiceCreated",
],
"default":null
}
]
}
]