|
Last week, we looked at 6 ways to version event schemas [1] and found the best solution is to avoid breaking changes and minimise the need for versioning. But how exactly do you do that? How can you prevent accidental breaking changes from creeping in? You can detect and stop breaking changes:
Here are three approaches you should consider. 1. Consumer-Driven ContractsIn consumer-driven contract testing, the consumer writes tests that express their expectations of the provider. These expectations become a contract file that the provider checks before making any change. This ensures the provider does not make changes that will break the consumers. Pact is a popular framework for consumer-driven contract testing. In a typical API-to-API scenario, a consumer test simulates an HTTP request and its expected JSON response, Pact captures that as a contract, and the provider verifies it before merging any changes. The same flow applies to events - the consumer test specifies the topic or queue plus the exact payload, Pact saves it as a message contract, and the event producer runs that pact to make sure its events match the consumer's expectations. Pros
Cons
2. Integration tests with schema packagesIn large organizations, getting widespread buy-in for consumer-driven contract testing is impractical without some sort of "shock event" that focuses the minds*. That's why the teams at LEGO took a different approach [2] to contract testing their event-driven architecture. The idea is pretty simple. Event publishers publish their schemas as NPM packages, and event consumers write tests against these packages. Pros
Cons
This approach is simple, but not very effective at catching breaking changes early. Instead, it focuses on giving consumers confidence that their code works against the latest event schema from the publisher. ----- * At a previous employer, we successfully introduced Pact due to several high-profile outages caused by integration issues. They gave us the political energy to align everyone's short-term priorities to push through an organization-wide change. As the saying goes, "Never let a good crisis go to waste". 3. Schema registry and broker-side validationBoth approaches above rely on testing to catch breaking changes during development. However, these are only as effective as their test coverage. PostNL takes yet another approach [3], which combines the use of a schema registry and an event broker. The schema registry serves as the single source of truth for event schemas. When a producer publishes an updated schema, the registry applies compatibility rules to make sure there are no breaking changes - e.g. fields are not removed, and their data types have not changed. If the change violates these rules, the registry rejects the schema, preventing incompatible versions from ever being registered. This provides early feedback to event publishers, preventing breaking changes before they go into production. Furthermore, as each event is ingested, the event broker looks up its schema in the registry and verifies that the payload matches the expected structure and data types. Invalid messages can be rejected, quarantined, or routed to a dead-letter queue, so only valid events reach consumers. Pros
Cons
SummaryConsumer‑driven contracts enforce each consumer’s exact event expectations at development time. It's ideal when you need to validate business‑specific rules and have teams buying into writing integration tests and achieving a high test coverage. Alternatively, publishers can share event schemas as code libraries for consumers to test against. This is simple to set up and does not require organization-wide buy-in to be effective. However, it's not effective in preventing breaking changes. Using a schema registry and broker-side validation gives you centralised governance and provides complete protection against breaking changes. However, it adds operational overhead and can't enforce business‑specific expectations. You can also combine these techniques. For example, use registry + broker validation to block accidental breaking changes and add consumer-driven contract tests to verify that specific business events fire exactly when and how you expect. Links[1] Event versioning strategies for event-driven architectures [2] How LEGO approaches contract testing [3] (Podcast) Event-driven architecture at PostNL with Luc van Donkersgoed |
Join 17K readers and level up you AWS game with just 5 mins a week.
Lambda Durable Functions is a powerful new feature, but its checkpoint + replay model has a few gotchas. Here are five to watch out for. Non-deterministic code The biggest gotcha is when the code is not deterministic. That is, it might do something different during replay. Remember, when a durable execution is replayed, the handler code is executed from the start. So the code must behave exactly the same given the same input. If you use random numbers, or timestamps to make branching...
Hi, I have just finished adding some content around Lambda Managed Instances (LMI) to my upcoming workshop. I put together a cheatsheet of the important ways that LMI is different from Lambda default and thought maybe you'd find it useful too. You can also download the PDF version below. Lambda default vs. Lambda managed instances.pdf
Two weeks ago, I gave you the biggest serverless announcements pre-re:Invent (see here). So here are the biggest serverless announcements during re:Invent 2025. Lambda Managed Instances Here’s the official announcement. A common pushback against Lambda is that “it’s expensive at scale” because: 1) Each execution environment can only process one request at a time, wasting available CPU cycles while you wait for IO response. 2) Paying for execution time is less efficient when handling thousands...