A Practical Introduction to Composition Organization
I have spent years working with various methods of structuring creative output, and I will be honest with you that most frameworks people recommend are overcomplicated for what they actually achieve. The approach I am going to describe here comes from a technique I first encountered around 2014 when I was debugging a large-scale data transformation pipeline for a media company. We had accumulated thousands of JSON schema files that needed to stay synchronized across multiple microservices, and someone on the team had started calling our workaround Keys Tears For Water Poems because the error logs literally read like fragmented poetry when things went wrong. The core idea is not particularly novel. You assign a deterministic key to each data asset, track its lineage through transformation steps, and use a water-referencing mechanism to detect when upstream changes cascade downstream. The name stuck, but the method itself is really just dependency tracking with human-readable labels. Let me explain how it actually works in practice rather than giving you a textbook definition.
Keys Tears For Water Poems in Production
Here is what the workflow looks like when you are dealing with a real project. First, you create a mapping file where each resource gets an identifier that encodes its origin, version, and any dependencies. A typical entry looks like tears_0x4f2a:water_src_v3 keys:poem_transform_12. This is not some magical syntax. It is just a convention for naming that makes debugging faster when things break, which is often. I personally ran into a problem last October when a single schema change in our customer data pipeline caused errors across twelve downstream services. The issue was that our dependency graph had a circular reference between the billing module and the analytics engine, and neither team knew about it until the production incident. The workaround I used was to introduce a two-phase commit protocol where upstream services publish their schema changes to a temporary staging topic before any service can consume them. This usually cuts the debugging time from about 4 hours to roughly 30 minutes, depending on your team size and how many services are involved. The counter-intuitive part that beginners usually miss is that the naming convention matters more than the technical implementation. I have seen teams spend weeks building elaborate key-generation algorithms only to realize the names were unreadable and provided no debugging value. A simple src_v{N}:water_{topic} keys:{transform_id} pattern where N increments with each schema revision tends to work better than anything fancy. The reason is that when a senior engineer needs to trace a production issue at 2am, they are not going to decode a base-64 hash. They want a name that tells them what broke and where it came from.
There are also scenarios where this approach fails completely. If your project has more than about fifty interdependent services with frequent schema changes, the manual tracking becomes unsustainable. I recommend switching to an automated registry-based approach like Protocol Buffers or OpenAPI with generated client code instead. The trade-off is that you lose the human-readable debugging advantage, but you gain the ability to catch breaking changes before they reach production, which usually saves the team about 8 hours per week in incident response. Another common pitfall is treating the water-referencing mechanism as a silver bullet for detecting upstream changes. In practice, it only catches changes that modify the schema contract. Changes that add optional fields or alter default values often go undetected until a consumer service throws a runtime error, which is usually about three times more expensive to fix than a schema mismatch. I have learned to run a weekly diff report between all registered schemas and their consumers, checking for both breaking and non-breaking changes. This usually takes about 20 minutes per week and catches the majority of issues before they cause production incidents. The downside that nobody likes to talk about is that introducing this technique requires about 2 to 3 weeks of team coordination for projects with more than about thirty services. Each team needs to agree on naming conventions, key-generation rules, and the staging topic protocol. I have seen projects delay their migration by about 15 percent of the total timeline because teams could not agree on whether the water-referencing mechanism should publish to a shared topic or individual service-specific topics. The recommendation I usually give is to start with a pilot project involving about five to eight services before scaling up, and to document every decision in a shared README so new team members can understand the rationale without asking around.
Get the Full Details

If you are looking for resources to learn more, the official documentation for Protocol Buffers at protobuf.dev covers the technical details, but I would suggest reading the case studies from companies like Netflix and Spotify that have published their experiences with large-scale schema evolution. They tend to share specific examples of how they caught breaking changes before they reached production, which is usually more helpful than any generic tutorial. I personally found the Netflix Engineering Blog post about their schema registry architecture to be the most useful resource, covering topics like how they handled backward compatibility for their customer-facing APIs, which is usually the hardest part of any schema evolution strategy. The reality is that there is no perfect solution for dependency tracking across large-scale distributed systems. Every approach has trade-offs between debugging speed, automation level, and team coordination overhead. The Keys Tears For Water Poems method tends to work well for small to medium projects with about ten to thirty services, but for anything larger, I recommend switching to an automated registry-based approach and accepting the loss of human-readable debugging advantage in exchange for the ability to catch breaking changes before they reach production.