Stop Ignoring Schema Evolution In Kafka
Cover photo by Conny Schneider on Unsplash
Why are you still passing raw JSON across your event bus? Stop doing that. You are setting yourself up for a production nightmare where one upstream change breaks everything downstream.
Versioning is a requirement, not a suggestion
I see teams treat their event schemas as an afterthought. They just publish whatever object their backend code happens to produce at that moment. This works fine until it doesn’t. When a downstream consumer expects a field to be an integer and gets a string, your pipeline stalls. I’ve been there, and I don’t want to go back.
Use a schema registry. Tools like Confluent or Apicurio exist for a reason. If you use something like Avro or Protobuf, you get compatibility checks for free.
// Good: Rigid structure with evolution support{ "type": "record", "name": "UserSignup", "fields": [ {"name": "id", "type": "string"}, {"name": "email", "type": "string", "default": ""} ]}You might say, “But my team is small and we talk all the time, so we don’t need this overhead.” That is fair for a prototype. It is a terrible strategy for anything that needs to survive six months of actual development (or a single Friday afternoon deployment). Even if you have total trust in your team, you still have to deal with your future self six months from now.
The reality of breaking changes
I admit that sometimes you really do need to make a breaking change. Maybe the business logic changed so drastically that your old event structure makes no sense. In those cases, don’t try to force backward compatibility. Just publish a new event type. Call it UserSignupV2.
// Instead of breaking V1, create a new topicproducer.send('user-signup-v2', payload);It feels messy to have multiple versions flying around, but it is better than a broken system. You can drain the old events, update your consumers at your own pace, and deprecate the old topic once traffic hits zero.
Do you really want to be the person debugging a dead-letter queue at 2 AM because of a missing field? I didn’t think so. It is far cheaper to fail at compile-time or CI time than it is to fix data corruption in your database after the fact. How are you handling schema drift in your current project?