Hardware FixRecommendedDevice not working? Your driver may be the problemCheck updates for common hardware issues.Fix DriversHalloween DealsAmazon USHalloween week deals: useful picks before month-endAmazon US: current deals, useful picks and tech finds.Check DealsClean PCRecommendedOne scan can reveal what keeps slowing WindowsLook for cleanup and repair opportunities.Run Scan×
FREEDOM251

Freedom251 › Blog › Apache Avro

Avro Schemas with Kafka: A 10-Minute Guide to Registry, SerDes, and Safe Evolution

By Freedom251 Team · · 11 min read

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Avro gives Kafka messages a precise, versioned data contract. A producer serializer turns an application record into bytes, a consumer deserializer reconstructs that record, and Schema Registry stores the schemas and checks whether new versions remain compatible. The practical path is: define a record, configure the Confluent Avro serializer and Schema Registry endpoint, publish to Kafka, configure the matching deserializer, and test every schema change against the subject that owns the record family.

This guide uses Confluent Schema Registry and its Kafka clients for concrete examples. Managed Confluent Cloud and self-hosted Confluent Platform expose the same core Registry-backed workflow, but their connection, authentication, and operational steps differ.

As an Amazon Associate I earn from qualifying purchases.

What Avro adds to a Kafka application

Kafka transports keys and values as byte arrays. Without a shared data contract, each producer and consumer must agree informally about field names, types, and how changes will be handled. Avro makes that contract explicit in a schema. The schema describes a named record and the type of each field; the serialized message carries data that a compatible reader can resolve back into a structured record.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Serialization and deserialization are separate responsibilities:

  • Serialization: the producer converts an in-memory record into bytes before sending it to Kafka.
  • Deserialization: the consumer converts those bytes into an application object or generic record.
  • Schema Registry: stores schema versions, associates them with subjects, and evaluates compatibility rules before a new version is accepted.

Avro can describe a key, a value, or both. A topic is the stream of records; a schema is the record definition; a subject is the Registry namespace in which a family of schema versions is tracked. A subject is not another Kafka topic.

Topic, schema, and subject: the names you must keep separate

Topic

A Kafka topic, such as transactions, stores ordered records. Each record has a key and a value, and either side may be serialized with Avro.

Schema

An Avro schema is usually a JSON document declaring a record name and fields. For example:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
{
  "type": "record",
  "name": "Transaction",
  "namespace": "com.example.payments",
  "fields": [
    {"name": "transaction_id", "type": "string"},
    {"name": "amount_cents", "type": "long"},
    {"name": "currency", "type": "string"}
  ]
}

The record name and namespace are part of the Avro identity. Field types are not interchangeable merely because their values look similar: a long, an int, and a string have different compatibility behavior.

Subject

A subject is the Schema Registry scope for versions and compatibility checks. Under Confluent’s usual topic naming convention, the value schema for transactions is registered under transactions-value, while an Avro key schema is registered under transactions-key. A change to the value subject is checked independently from a change to the key subject.

Because subjects define schema families, verify the subject name before diagnosing an evolution error. Registering a record under an unexpected subject can make an apparently safe change look unrelated to the existing data.

The Registry-backed producer and consumer path

The workflow below is the shortest reliable route from an Avro definition to a running application. The class names are the Confluent Kafka client classes; other Registry implementations may use different serializers, configuration keys, or wire formats.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  1. Define the record schema. Give the record a stable name, declare every field type, and decide which fields are required or nullable.
  2. Choose the subject. For the normal topic-based naming strategy, a value goes to <topic>-value and a key goes to <topic>-key.
  3. Configure the producer. Set the Kafka bootstrap servers, the appropriate key serializer, the Confluent Avro value serializer, and the Schema Registry URL.
  4. Produce records. The serializer resolves the record schema against the Registry subject and sends the encoded value to Kafka.
  5. Configure the consumer. Point it at the same Kafka cluster and Registry, and use the matching Confluent Avro deserializer for the side encoded as Avro.
  6. Read and inspect the result. Confirm that field names and types in the deserialized record match the application model.
  7. Test the next version before rollout. Ask the Registry to evaluate the candidate schema under the subject’s configured compatibility rule, then deploy producers and consumers in an order that the rule supports.

Define a schema that can evolve

Start with fields that have clear business meaning and stable types. Use a record name that identifies the entity rather than a temporary implementation detail. Avoid embedding a version number in every record name; versions are tracked by the subject, while the record name should remain stable when the logical record remains the same.

Required fields

A required field is present in the original schema and has no null branch. Existing data contains it, so a reader normally does not need a fallback. Removing or changing such a field can break readers and should be evaluated explicitly against the compatibility mode.

Nullable fields and defaults

In Avro, nullability is expressed with a union containing "null". A common optional field declaration is:

{
  "name": "customer_id",
  "type": ["null", "string"],
  "default": null
}

Two details matter. First, the union includes "null"; merely adding a default to a plain "string" field does not make that field nullable. Second, the default must conform to the first branch of the union. Because "null" is first, the default above is null. If "string" came first, a string default would be required instead.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The default has a specific job during schema resolution: when a new reader encounters an older record that lacks the newly added field, it can supply the declared value. It is not the same thing as saying that every producer will write a value, and it does not by itself make every schema change compatible.

Configure a Confluent Avro producer

The following Java properties show the essential roles. Replace the endpoint and Kafka connection details with those for your Confluent Cloud or Confluent Platform environment; authentication properties are deployment-specific.

Properties props = new Properties();
props.put("bootstrap.servers", "kafka.example:9092");
props.put("key.serializer",
          "org.apache.kafka.common.serialization.StringSerializer");
props.put("value.serializer",
          "io.confluent.kafka.serializers.KafkaAvroSerializer");
props.put("schema.registry.url", "https://registry.example");

KafkaAvroSerializer is the value serializer in this example. If the key is also Avro, configure the key serializer as the corresponding Avro serializer and supply a key schema; if the key is a string or another format, keep its native serializer. Do not assume that choosing Avro for values automatically changes key serialization.

Create the record using the representation expected by your client library, send it to the intended topic, and handle ordinary Kafka delivery errors separately from Registry compatibility errors. A Registry rejection means the schema policy blocked the candidate schema; it is not evidence that the Kafka broker is unavailable.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Configure the matching consumer

A consumer must connect to the same Registry that contains the schemas needed to resolve the records it reads. For an Avro value, use the Confluent deserializer:

Properties props = new Properties();
props.put("bootstrap.servers", "kafka.example:9092");
props.put("group.id", "transactions-reader");
props.put("key.deserializer",
          "org.apache.kafka.common.serialization.StringDeserializer");
props.put("value.deserializer",
          "io.confluent.kafka.serializers.KafkaAvroDeserializer");
props.put("schema.registry.url", "https://registry.example");

Use a key deserializer that matches how the producer encoded keys. A string key paired with an Avro value is normal; so is Avro on both sides. After polling, inspect the returned generic or specific record according to your application’s model. A consumer that points to the wrong Registry, subject, or authentication context may fail before it can interpret any Kafka data.

Console verification

Confluent Platform documents console producer and consumer tooling for trying the same path without writing a full application. Keep those commands scoped to the Platform environment in which they are documented. Cloud connection details, credentials, and command-line options differ, so do not copy an on-premises command unchanged into a managed deployment.

How Schema Registry checks evolution

Compatibility describes which writer and reader schema versions can interpret one another’s data. The direction matters because Kafka consumers may be reading records produced earlier, while a rolling deployment can temporarily leave old consumers running beside new producers.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Mode What must work When it helps
BACKWARD A consumer using the new schema can read data written with the preceding schema. Useful when consumers may rewind and process earlier Kafka records.
FORWARD A consumer using the preceding schema can read data written with the new schema. Useful when old consumers must continue while producers move first.
FULL Both backward and forward directions hold between the compared versions. Useful when either rollout order must remain readable.
BACKWARD_TRANSITIVE The new schema can read data from every earlier version, not only the immediately previous one. Protects long-lived topics with multiple historical schema versions.
FORWARD_TRANSITIVE Every earlier reader can read data written with the new schema. Protects deployments that retain old consumers across several releases.
FULL_TRANSITIVE Both directions are checked against all earlier versions. Strongest historical guarantee, with fewer changes accepted.

Confluent Schema Registry documents BACKWARD as its default compatibility mode. That default belongs to the Registry configuration in question; verify the setting for your subject and deployment rather than assuming every Registry installation uses it.

“Backward” does not mean “anything that looks optional is safe.” It means the new reader can resolve records written by the prior writer schema. A field addition, removal, type change, or renamed field must be tested according to the actual Avro resolution rules and the subject’s policy.

A safe field addition, step by step

Version 1

{
  "type": "record",
  "name": "Order",
  "fields": [
    {"name": "order_id", "type": "string"},
    {"name": "total_cents", "type": "long"}
  ]
}

Version 2 with an optional identifier

{
  "type": "record",
  "name": "Order",
  "fields": [
    {"name": "order_id", "type": "string"},
    {"name": "total_cents", "type": "long"},
    {"name": "customer_id", "type": ["null", "string"], "default": null}
  ]
}

Under a backward-compatible policy, a new consumer can read Version 1 records because it supplies null for the missing customer_id. Before publishing Version 2, run the Registry compatibility check for the exact subject, such as orders-value. Then deploy the consumer that understands the field and the producer that may populate it. Existing records remain interpretable because the reader has a conforming fallback.

If the business rule requires every new record to contain a customer identifier, use a required field only after the rollout plan guarantees that all records the reader must process contain it. Making a field nullable is a data-model decision, not merely a compatibility trick.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Compatibility testing belongs in the release process

  1. Identify the subject. Check whether the change affects the key or value and use the corresponding subject.
  2. Fetch the effective policy. A subject can have a setting that differs from the Registry-wide default.
  3. Submit the candidate schema for compatibility evaluation. Test it against the policy before registering it as the producer’s active version.
  4. Test real reader and writer combinations. At minimum, exercise the previous writer with the new reader for backward mode, or the previous reader with the new writer for forward mode. For transitive policies, include representative older versions.
  5. Roll out in the order implied by the policy. A backward policy generally supports updating consumers before producers; a forward policy is chosen when older consumers must read new data.
  6. Keep rollback data-compatible. A binary application rollback is not enough if the rolled-back reader cannot resolve records already written by the newer producer.

Compatibility checks do not replace application-level tests. Avro can confirm that a field is technically resolvable while your business logic still mishandles a new value, a changed meaning, or a newly permitted null.

Managed Registry or self-hosted Platform?

The documented tutorials cover both Confluent Cloud Schema Registry and Confluent Platform. The core subject and compatibility concepts are the same, but operational ownership is different.

Decision axis Managed Confluent Cloud Self-hosted Confluent Platform
Operational ownership The service provider operates the managed Registry; your team configures clients, access, and subjects. Your team operates the Registry deployment, upgrades, availability, and backups.
Deployment environment Access is through the cloud service endpoint and its connection and authentication requirements. Access is through infrastructure you control, such as an internal network or data center.
Security and configuration Use the cloud-specific credentials, endpoint, and security properties supplied for the environment. Configure network exposure, authentication, authorization, certificates, and storage according to your Platform installation.
Availability work Plan for service access and client-side failure handling without operating Registry servers. Plan capacity, replication, monitoring, upgrades, and disaster recovery for the Registry service.

Choose based on who should run the control plane and where Kafka already operates. Do not treat the cloud tutorial’s endpoint or credentials as interchangeable with an on-premises installation.

Common failures and the fastest diagnosis

The producer cannot register a schema

  • Confirm the Schema Registry URL is reachable from the producer runtime.
  • Check authentication and TLS settings for the selected environment.
  • Verify that the producer is targeting the intended topic and therefore the intended key or value subject.
  • Read the compatibility error as a schema-policy failure first; changing Kafka broker settings will not make an incompatible schema valid.

The consumer cannot deserialize records

  • Ensure the consumer uses KafkaAvroDeserializer for an Avro-encoded side.
  • Point it to the Registry that contains the writer schema versions referenced by the topic’s records.
  • Match key and value deserializers independently; a string key does not need an Avro key deserializer.
  • Check that the consumer’s identity can read the Registry subject and schema versions.

An added field breaks old data

  • For a field absent from old records, add a union containing "null" and a default of null, with "null" first.
  • Run the subject-level compatibility check instead of relying on a local parser.
  • Confirm that the field’s business meaning permits null; technical readability does not make missing data valid for every application.

A change passes locally but fails in deployment

  • Compare the local and deployed subject names.
  • Compare effective compatibility settings; the documented Confluent default is BACKWARD, but an individual subject or installation may differ.
  • Check that the deployed client versions and serializer configuration match the environment for which the test was performed.

Practical design checklist

  • Keep record names stable for the same logical entity.
  • Document whether each field is required, nullable, or populated by a reader default.
  • Use separate subject checks for Avro keys and values.
  • Never assume a default makes a non-nullable field optional.
  • Make the union’s first branch agree with its default.
  • Test the exact candidate schema against the subject policy before release.
  • Account for consumers that rewind and process historical Kafka records.
  • Include representative old and new records in integration tests.
  • Keep cloud and self-hosted connection instructions separate.
  • Record the Registry endpoint and effective subject policy as part of deployment configuration, not application code assumptions.

What to remember in one minute

Avro defines the structure, Kafka carries the bytes, serializers and deserializers bridge application objects to those bytes, and Schema Registry governs versions. Subjects—not topics—are where schema families and compatibility rules live. For a typical transactions topic, use transactions-value for the value schema and transactions-key for an Avro key. Compatibility is directional, transitive modes include all earlier versions, and Confluent Schema Registry documents BACKWARD as its default. When adding a field that older records do not have, use a union such as ["null", "string"] with "default": null, then run the subject’s compatibility check before rollout.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Apache AvroApache KafkaConfluentKafka developersschema evolutionSchema Registry

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Recommended PC Tool
Recommended PC Tool
PC Slower Than It Used to Be?Free scan - under a minute
Outdated Drivers Are Slowing You DownFree scan - exact matches

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.