Skip to content

AxonOps — AI-Native Control Plane for Open Source Data Platforms

Schema Formats

Schema Registry supports multiple serialization formats for data contracts in Kafka topics.


FeatureAvroProtobufJSON Schema
Binary encodingYesYesNo
Schema evolutionExcellentGoodLimited
Human readableNoNoYes
Code generationYesYesOptional
Default valuesYesYesYes
Backward compatibilityNativeNativeManual
Size efficiencyHighHighestLow

Apache Avro provides compact binary serialization with strong schema evolution support.

{
"type": "record",
"name": "User",
"namespace": "com.example.events",
"fields": [
{
"name": "id",
"type": "string",
"doc": "Unique user identifier"
},
{
"name": "email",
"type": "string"
},
{
"name": "created_at",
"type": {
"type": "long",
"logicalType": "timestamp-millis"
}
},
{
"name": "status",
"type": {
"type": "enum",
"name": "UserStatus",
"symbols": ["ACTIVE", "INACTIVE", "PENDING"]
},
"default": "PENDING"
},
{
"name": "metadata",
"type": ["null", {
"type": "map",
"values": "string"
}],
"default": null
}
]
}
TypeDescriptionExample
nullNo valuenull
booleanTrue/falsetrue
int32-bit signed42
long64-bit signed1234567890
float32-bit IEEE 7543.14
double64-bit IEEE 7543.14159265
bytesByte sequenceBinary data
stringUTF-8 string"hello"
arrayOrdered collection[1, 2, 3]
mapKey-value pairs{"key": "value"}
recordNamed fieldsComplex type
enumEnumeration"ACTIVE"
fixedFixed-size bytesUUID, hash
unionType alternatives["null", "string"]
{
"type": "record",
"name": "Transaction",
"fields": [
{
"name": "amount",
"type": {
"type": "bytes",
"logicalType": "decimal",
"precision": 10,
"scale": 2
}
},
{
"name": "transaction_date",
"type": {
"type": "int",
"logicalType": "date"
}
},
{
"name": "transaction_time",
"type": {
"type": "long",
"logicalType": "timestamp-millis"
}
},
{
"name": "transaction_id",
"type": {
"type": "fixed",
"name": "uuid",
"size": 16,
"logicalType": "uuid"
}
}
]
}
Logical TypeUnderlying TypeDescription
decimalbytes/fixedArbitrary precision decimal
dateintDays from Unix epoch
time-millisintMilliseconds from midnight
time-microslongMicroseconds from midnight
timestamp-millislongMilliseconds from epoch
timestamp-microslongMicroseconds from epoch
uuidstring/fixedUUID string or 16 bytes
Properties props = new Properties();
props.put("bootstrap.servers", "kafka: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", "http://schema-registry:8081");
KafkaProducer<String, User> producer = new KafkaProducer<>(props);
User user = User.newBuilder()
.setId("user-123")
.setEmail("user@example.com")
.setCreatedAt(System.currentTimeMillis())
.setStatus(UserStatus.ACTIVE)
.build();
producer.send(new ProducerRecord<>("users", user.getId(), user));
from confluent_kafka import Consumer
from confluent_kafka.schema_registry import SchemaRegistryClient
from confluent_kafka.schema_registry.avro import AvroDeserializer
schema_registry_client = SchemaRegistryClient({'url': 'http://schema-registry:8081'})
avro_deserializer = AvroDeserializer(schema_registry_client)
consumer = Consumer({
'bootstrap.servers': 'kafka:9092',
'group.id': 'my-consumer-group',
'value.deserializer': avro_deserializer
})
consumer.subscribe(['users'])
while True:
msg = consumer.poll(1.0)
if msg is not None:
user = msg.value()
print(f"User: {user['id']}, Email: {user['email']}")

Protocol Buffers provide efficient binary serialization with strong typing and code generation.

syntax = "proto3";
package com.example.events;
import "google/protobuf/timestamp.proto";
message User {
string id = 1;
string email = 2;
google.protobuf.Timestamp created_at = 3;
UserStatus status = 4;
map<string, string> metadata = 5;
enum UserStatus {
USER_STATUS_UNSPECIFIED = 0;
USER_STATUS_ACTIVE = 1;
USER_STATUS_INACTIVE = 2;
USER_STATUS_PENDING = 3;
}
}
message UserEvent {
string event_id = 1;
EventType event_type = 2;
User user = 3;
google.protobuf.Timestamp event_time = 4;
enum EventType {
EVENT_TYPE_UNSPECIFIED = 0;
EVENT_TYPE_CREATED = 1;
EVENT_TYPE_UPDATED = 2;
EVENT_TYPE_DELETED = 3;
}
}
TypeDescriptionDefault Value
double64-bit float0.0
float32-bit float0.0
int32Variable-length signed0
int64Variable-length signed0
uint32Variable-length unsigned0
uint64Variable-length unsigned0
sint32ZigZag encoded signed0
sint64ZigZag encoded signed0
fixed32Fixed 4 bytes unsigned0
fixed64Fixed 8 bytes unsigned0
sfixed32Fixed 4 bytes signed0
sfixed64Fixed 8 bytes signed0
boolBooleanfalse
stringUTF-8 string""
bytesByte sequenceempty
Properties props = new Properties();
props.put("bootstrap.servers", "kafka:9092");
props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
props.put("value.serializer", "io.confluent.kafka.serializers.protobuf.KafkaProtobufSerializer");
props.put("schema.registry.url", "http://schema-registry:8081");
KafkaProducer<String, User> producer = new KafkaProducer<>(props);
User user = User.newBuilder()
.setId("user-123")
.setEmail("user@example.com")
.setCreatedAt(Timestamps.fromMillis(System.currentTimeMillis()))
.setStatus(UserStatus.USER_STATUS_ACTIVE)
.build();
producer.send(new ProducerRecord<>("users", user.getId(), user));

JSON Schema provides human-readable validation with broad tooling support.

{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "com.example.events.User",
"type": "object",
"title": "User",
"required": ["id", "email"],
"properties": {
"id": {
"type": "string",
"description": "Unique user identifier"
},
"email": {
"type": "string",
"format": "email"
},
"created_at": {
"type": "string",
"format": "date-time"
},
"status": {
"type": "string",
"enum": ["ACTIVE", "INACTIVE", "PENDING"],
"default": "PENDING"
},
"age": {
"type": "integer",
"minimum": 0,
"maximum": 150
},
"tags": {
"type": "array",
"items": {
"type": "string"
}
},
"metadata": {
"type": "object",
"additionalProperties": {
"type": "string"
}
}
}
}
TypeDescriptionValidation Keywords
stringTextminLength, maxLength, pattern, format
numberFloating pointminimum, maximum, multipleOf
integerWhole numberminimum, maximum, multipleOf
booleanTrue/false-
objectKey-valueproperties, required, additionalProperties
arrayOrdered listitems, minItems, maxItems, uniqueItems
nullNo value-
FormatDescription
date-timeISO 8601 date-time
dateISO 8601 date
timeISO 8601 time
emailEmail address
hostnameHostname
ipv4IPv4 address
ipv6IPv6 address
uriURI
uuidUUID
Properties props = new Properties();
props.put("bootstrap.servers", "kafka:9092");
props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
props.put("value.serializer", "io.confluent.kafka.serializers.json.KafkaJsonSchemaSerializer");
props.put("schema.registry.url", "http://schema-registry:8081");
props.put("json.fail.invalid.schema", "true");
KafkaProducer<String, User> producer = new KafkaProducer<>(props);
User user = new User();
user.setId("user-123");
user.setEmail("user@example.com");
user.setStatus("ACTIVE");
producer.send(new ProducerRecord<>("users", user.getId(), user));

Terminal window
# Register Avro schema
curl -X POST http://schema-registry:8081/subjects/users-value/versions \
-H "Content-Type: application/vnd.schemaregistry.v1+json" \
-d '{
"schemaType": "AVRO",
"schema": "{\"type\":\"record\",\"name\":\"User\",\"fields\":[{\"name\":\"id\",\"type\":\"string\"},{\"name\":\"email\",\"type\":\"string\"}]}"
}'
# Register Protobuf schema
curl -X POST http://schema-registry:8081/subjects/users-value/versions \
-H "Content-Type: application/vnd.schemaregistry.v1+json" \
-d '{
"schemaType": "PROTOBUF",
"schema": "syntax = \"proto3\"; message User { string id = 1; string email = 2; }"
}'
# Register JSON Schema
curl -X POST http://schema-registry:8081/subjects/users-value/versions \
-H "Content-Type: application/vnd.schemaregistry.v1+json" \
-d '{
"schemaType": "JSON",
"schema": "{\"type\":\"object\",\"properties\":{\"id\":{\"type\":\"string\"},\"email\":{\"type\":\"string\"}}}"
}'
Terminal window
# Get latest schema
curl http://schema-registry:8081/subjects/users-value/versions/latest
# Get specific version
curl http://schema-registry:8081/subjects/users-value/versions/1
# Get schema by ID
curl http://schema-registry:8081/schemas/ids/1
Terminal window
curl http://schema-registry:8081/subjects

PropertyDescriptionDefault
schema.registry.urlRegistry URLRequired
auto.register.schemasAuto-register schemastrue
use.latest.versionUse latest schema versionfalse
avro.use.logical.type.convertersUse logical type convertersfalse
PropertyDescriptionDefault
schema.registry.urlRegistry URLRequired
auto.register.schemasAuto-register schemastrue
reference.subject.name.strategyReference naming strategy-
PropertyDescriptionDefault
schema.registry.urlRegistry URLRequired
auto.register.schemasAuto-register schemastrue
json.fail.invalid.schemaFail on invalid schemafalse
json.oneof.for.nullablesUse oneOf for nullablefalse