Confluent Schema Registry is a well-designed tool that solves a specific and important problem: ensuring that messages written to Kafka topics conform to registered schemas, and that schema evolution follows compatibility rules your consumers can handle. If you're running Kafka with Avro or Protobuf, you should be using it.
This post isn't a criticism of Schema Registry. It's a clarification of its boundaries: what it's designed to do, what it explicitly doesn't do, and where the gap between "message is schema-valid" and "pipeline is data-healthy" lives. That gap is where Streamforge operates.
What Schema Registry Actually Validates
Schema Registry validates two things:
At produce time: the producer's message conforms to a registered schema. The registry looks up the schema ID embedded in the message header, fetches the corresponding schema definition, and validates that the message can be deserialized against it. If it can't, the produce call is rejected.
At schema update time: the new schema version is compatible with previous versions under the configured compatibility mode (BACKWARD, FORWARD, FULL, or NONE). Adding an optional field is backward-compatible. Removing a required field is not.
These are structural guarantees. They're powerful and important. They prevent a large class of consumer deserialization failures that used to be common before Schema Registry became standard practice.
What Schema Registry Doesn't Validate
Schema Registry doesn't validate the data values inside a structurally-valid message. Once a message passes the schema conformance check, its field values are treated as opaque. There's no mechanism to say "this float field should always be positive" or "this string field should always be one of these 12 known values" or "this timestamp field should always be within 10 minutes of the current wall clock time."
That's not a design flaw. Value-range validation is a fundamentally different problem from structural validation, and embedding it in the schema registry would require a much more complex constraint language and runtime evaluation. The registry is doing what it's designed to do.
The consequence is that these classes of data problems flow through a Schema Registry-protected pipeline without any alarm:
- Optional field population drift: a field defined as
union[null, string]starts being null 60% of the time instead of the usual 2%. Schema-valid. Semantically broken for consumers that depend on that field. - Value range anomalies: an order total field starts sending values of
0.0for 15% of events, because a producer bug is failing to populate the price computation. The float type is valid. The value is wrong. - Enum vocabulary expansion: a status field that historically carried only
["pending", "processing", "shipped", "delivered"]starts producing"refunded"values after a producer update. The string type is valid. Downstream consumers with switch statements on the status field hit the default case silently. - Cross-topic key drift: two topics are supposed to share an order ID format that allows joining. One producer starts generating a subtly different ID format (say, uppercase vs lowercase UUIDs). Both topics look healthy individually. The join produces no matches.
The Backward Compatibility Trap
Schema Registry's BACKWARD compatibility mode is the most common configuration. It ensures that consumers using schema version N can read messages written with schema version N+1. The typical producer workflow: add a new field with a default value, register the new schema version, deploy the producer.
The problem is that BACKWARD compatibility only considers structural changes to the schema. A producer could remove a field, add it back with the same name but a slightly different semantic meaning, and BACKWARD compatibility would allow it because the type is unchanged. Consumers that were relying on the old semantic meaning now get the new one silently.
We hit a version of this in a logistics pipeline where a field called estimated_delivery_hours was changed from representing hours-until-delivery to representing total-transit-hours (including already-elapsed hours). Same field name, same int type, backward-compatible schema change. Every consumer that displayed "estimated delivery" to users started showing inflated numbers. The schema was perfectly valid at every level.
The Gap Streamforge Fills
Rather than trying to extend Schema Registry with runtime constraints (which would require changing how the registry works), we watch traffic from the outside. Streamforge observes what events actually look like over a learning window and builds a probabilistic baseline for each field on each topic. Deviations from that baseline are the signal.
This approach is complementary to Schema Registry rather than competitive with it. Schema Registry enforces what the schema says. Streamforge monitors what the data actually does. Together they cover the full envelope: structural validity at produce time, plus semantic health at runtime.
For teams using Confluent Cloud specifically, the integration is via the standard Kafka consumer API. Streamforge consumes a copy of the topic events alongside your existing consumers, computes field-level statistics, and fires alerts when the statistics deviate from baseline. It doesn't modify the Schema Registry configuration and doesn't interfere with the produce-time validation flow.
The Question of Compatibility Mode Choice
One operational decision that Schema Registry leaves to teams is which compatibility mode to use. NONE compatibility gives producers maximum flexibility but removes all backward-compatibility guarantees. FULL compatibility is the strictest: both forward and backward compatible. Most teams land on BACKWARD.
We're not saying one choice is always right. The tradeoff is between schema evolution velocity and consumer stability. The important thing is to understand what the choice does and doesn't guarantee, because teams sometimes interpret "BACKWARD compatible" as "safe for all consumers," which it isn't. BACKWARD compatibility means existing consumers can read new messages. It doesn't mean all consumers will interpret the new messages correctly if any semantic meaning has changed.
What a Complete Schema Governance Layer Looks Like
The full picture of what a well-governed Kafka pipeline validates:
- Structural conformance at produce time: Schema Registry handles this. Every message must conform to a registered schema. No bypassing this.
- Schema evolution governance: Schema Registry handles this too, via compatibility mode. New schema versions must be reviewed and registered before producers can use them.
- Runtime semantic health: This is the gap. Field presence rates, value ranges, type distributions, and cross-topic correlation consistency. This is what Streamforge monitors.
- Consumer impact visibility: When a schema anomaly is detected, which consumers are affected? What's the blast radius? This requires the topic dependency graph that Schema Registry doesn't maintain but Streamforge does.
Schema Registry is the right first layer. Runtime monitoring is the second layer. Teams that have only the first layer will eventually hit the kinds of silent corruption described above. The question is whether they find it in 15 minutes or 36 hours.