Kafka Connect and Schema Registry¶
π Kafka Connect - Connect framework documentation π Schema Registry - Schema Registry documentation
Kafka Connect Overview¶
Architecture¶
π Connect Architecture - Connect architecture and concepts
Core Components: - Workers - JVM processes that execute connectors and tasks - Connectors - Logical jobs that define source/sink configuration - Tasks - Units of work that actually move data - Converters - Serialize/deserialize data between Connect and Kafka - Transforms - Optional record modifications (Single Message Transforms)
Worker Modes¶
Standalone Mode: - Single worker process - Configuration stored in local files - No fault tolerance or scalability - Good for development and testing - Started with: connect-standalone.sh worker.properties connector.properties
Distributed Mode: - Multiple worker processes form a Connect cluster - Configuration stored in Kafka topics (distributed, fault-tolerant) - Automatic task distribution and rebalancing - Managed via REST API - Started with: connect-distributed.sh worker.properties
π Distributed Mode - Distributed worker configuration
Worker Configuration¶
Key Settings: - bootstrap.servers - Kafka cluster address - group.id - Connect cluster group ID (distributed mode) - config.storage.topic - Topic for connector configurations - offset.storage.topic - Topic for source connector offsets - status.storage.topic - Topic for connector/task status - key.converter - Default key converter - value.converter - Default value converter - plugin.path - Directories for connector plugins
Converters¶
| Converter | Class | Use Case |
|---|---|---|
| JSON | org.apache.kafka.connect.json.JsonConverter | Human-readable, schema optional |
| Avro | io.confluent.connect.avro.AvroConverter | Schema Registry, compact binary |
| Protobuf | io.confluent.connect.protobuf.ProtobufConverter | Schema Registry, language-neutral |
| JSON Schema | io.confluent.connect.json.JsonSchemaConverter | Schema Registry, JSON with schema |
| String | org.apache.kafka.connect.storage.StringConverter | Plain text |
| ByteArray | org.apache.kafka.connect.converters.ByteArrayConverter | Raw bytes |
Important: Converters handle serialization between Connect's internal data format and Kafka. They are configured at the worker level (default) or per connector (override).
Connector Configuration¶
Source Connectors¶
- Read data from external systems into Kafka topics
- Track source offsets for exactly-once delivery
- Examples: JDBC Source, Debezium (CDC), FileStream Source
Sink Connectors¶
- Write data from Kafka topics to external systems
- Track consumer offsets for delivery guarantees
- Examples: JDBC Sink, Elasticsearch Sink, S3 Sink
Common Configuration Properties¶
{
"name": "my-connector",
"config": {
"connector.class": "io.confluent.connect.jdbc.JdbcSourceConnector",
"tasks.max": "3",
"key.converter": "org.apache.kafka.connect.storage.StringConverter",
"value.converter": "io.confluent.connect.avro.AvroConverter",
"value.converter.schema.registry.url": "http://localhost:8081",
"transforms": "route,timestamp",
"transforms.route.type": "org.apache.kafka.connect.transforms.RegexRouter",
"transforms.route.regex": "(.*)",
"transforms.route.replacement": "prefix-$1"
}
}
Task Parallelism¶
tasks.max- Maximum number of tasks for the connector- Actual task count may be less than
tasks.max(depends on data) - Source connectors: tasks partition the data source
- Sink connectors: tasks are assigned Kafka partitions
- More tasks = higher parallelism (up to partition count for sinks)
Single Message Transforms (SMTs)¶
π SMT Documentation - Available transforms and configuration
Built-in Transforms¶
| Transform | Description |
|---|---|
InsertField | Add a field using static value or record metadata |
ReplaceField | Filter or rename fields |
MaskField | Replace field value with valid null or zero equivalent |
ValueToKey | Set the record key from a value field |
HoistField | Wrap entire value as a single field |
ExtractField | Extract a single field from a struct |
SetSchemaMetadata | Modify schema name or version |
TimestampRouter | Modify topic name based on timestamp |
RegexRouter | Modify topic name based on regex |
Flatten | Flatten nested structs |
Cast | Cast fields to different types |
TimestampConverter | Convert between timestamp formats |
Filter | Drop records based on a predicate |
InsertHeader | Add a header to the record |
HeaderFrom | Move/copy fields to headers |
DropHeaders | Remove headers |
Transform Chain¶
{
"transforms": "addTimestamp,route",
"transforms.addTimestamp.type": "org.apache.kafka.connect.transforms.InsertField$Value",
"transforms.addTimestamp.timestamp.field": "processed_at",
"transforms.route.type": "org.apache.kafka.connect.transforms.RegexRouter",
"transforms.route.regex": "(.*)",
"transforms.route.replacement": "processed-$1"
}
$Key) or value ($Value) - Transforms are lightweight - for complex logic use Kafka Streams Error Handling¶
π Error Handling - Dead letter queues and error tolerance
Error Tolerance¶
errors.tolerance=none(default) - Fail on first errorerrors.tolerance=all- Skip bad records, continue processing
Dead Letter Queue (DLQ)¶
{
"errors.tolerance": "all",
"errors.deadletterqueue.topic.name": "my-connector-dlq",
"errors.deadletterqueue.topic.replication.factor": 3,
"errors.deadletterqueue.context.headers.enable": true
}
Error Logging¶
{
"errors.log.enable": true,
"errors.log.include.messages": true
}
Connect REST API¶
π REST API Reference - Complete REST API documentation
Key Endpoints¶
| Method | Endpoint | Description |
|---|---|---|
| GET | /connectors | List all connectors |
| POST | /connectors | Create a new connector |
| GET | /connectors/{name} | Get connector info |
| GET | /connectors/{name}/config | Get connector config |
| PUT | /connectors/{name}/config | Update connector config |
| GET | /connectors/{name}/status | Get connector status |
| POST | /connectors/{name}/restart | Restart connector |
| PUT | /connectors/{name}/pause | Pause connector |
| PUT | /connectors/{name}/resume | Resume connector |
| DELETE | /connectors/{name} | Delete connector |
| GET | /connectors/{name}/tasks | List tasks |
| POST | /connectors/{name}/tasks/{id}/restart | Restart task |
| GET | /connector-plugins | List available plugins |
| PUT | /connector-plugins/{name}/config/validate | Validate config |
Schema Registry¶
Overview¶
π Schema Registry Overview - Schema Registry fundamentals
- Centralized schema management for Kafka
- Stores schemas for Kafka topics (key and value)
- Enforces schema compatibility rules
- Supports Avro, Protobuf, and JSON Schema
- Schemas stored in the
_schemasinternal topic - REST API for schema management
Subjects and Naming¶
Subject Naming Strategies: - TopicNameStrategy (default) - Subject name: <topic>-key / <topic>-value - RecordNameStrategy - Subject name: <fully-qualified-record-name> - TopicRecordNameStrategy - Subject name: <topic>-<fully-qualified-record-name>
π Subject Name Strategy - Configuring subject naming
Schema IDs¶
- Each schema version is assigned a globally unique integer ID
- IDs are sequential and never reused
- Producers include the schema ID in the message (first 5 bytes: magic byte + 4-byte ID)
- Consumers use the schema ID to retrieve the schema from the registry
Schema Compatibility¶
π Schema Evolution - Compatibility types and rules
Compatibility Types¶
| Mode | Description | Allowed Changes |
|---|---|---|
| BACKWARD | New schema reads old data | Add optional field, delete field |
| FORWARD | Old schema reads new data | Delete optional field, add field |
| FULL | Both backward and forward | Add/delete optional fields with defaults |
| BACKWARD_TRANSITIVE | Backward with all versions | Same as BACKWARD, checked against all |
| FORWARD_TRANSITIVE | Forward with all versions | Same as FORWARD, checked against all |
| FULL_TRANSITIVE | Full with all versions | Same as FULL, checked against all |
| NONE | No compatibility checks | Any change allowed |
Compatibility Rules for Avro¶
BACKWARD Compatible Changes: - Add a field with a default value - Remove a field (that had a default in old schema)
FORWARD Compatible Changes: - Remove a field that has a default value - Add a field (that has a default in new schema)
FULL Compatible Changes: - Add a field with a default value (when old schema also has default) - Remove a field that has a default value
Breaking Changes (all modes): - Change field type (int to string) - Rename a field without alias - Remove a required field (no default) - Add a required field (no default)
Compatibility Quick Reference¶
| Change | BACKWARD | FORWARD | FULL |
|---|---|---|---|
| Add field with default | Yes | Yes | Yes |
| Add field without default | No | Yes | No |
| Remove field with default | Yes | Yes | Yes |
| Remove field without default | Yes | No | No |
| Change field type | No | No | No |
Schema Registry REST API¶
π Schema Registry API - Complete API reference
Key Endpoints¶
| Method | Endpoint | Description |
|---|---|---|
| GET | /subjects | List all subjects |
| GET | /subjects/{subject}/versions | List versions for a subject |
| GET | /subjects/{subject}/versions/{version} | Get schema by version |
| POST | /subjects/{subject}/versions | Register a new schema |
| POST | /compatibility/subjects/{subject}/versions/{version} | Test compatibility |
| GET | /schemas/ids/{id} | Get schema by global ID |
| GET | /config | Get global compatibility level |
| PUT | /config | Set global compatibility level |
| GET | /config/{subject} | Get subject compatibility level |
| PUT | /config/{subject} | Set subject compatibility level |
| DELETE | /subjects/{subject} | Delete subject (soft delete) |
| DELETE | /subjects/{subject}?permanent=true | Permanent delete |
Schema Registration Example¶
# Register a new Avro schema
curl -X POST -H "Content-Type: application/vnd.schemaregistry.v1+json" \
--data '{"schema": "{\"type\":\"record\",\"name\":\"User\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"age\",\"type\":\"int\"}]}"}' \
http://localhost:8081/subjects/users-value/versions
# Check compatibility
curl -X POST -H "Content-Type: application/vnd.schemaregistry.v1+json" \
--data '{"schema": "{\"type\":\"record\",\"name\":\"User\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"age\",\"type\":\"int\"},{\"name\":\"email\",\"type\":[\"null\",\"string\"],\"default\":null}]}"}' \
http://localhost:8081/compatibility/subjects/users-value/versions/latest
Avro, Protobuf, and JSON Schema¶
Avro¶
- Binary format with schema
- Schema defined in JSON
- Compact serialization
- Rich type system (records, enums, arrays, maps, unions)
- Schema evolution with defaults and unions
- Most common format with Confluent Schema Registry
Protobuf¶
- Binary format defined by Google
- Schema defined in
.protofiles - Language-neutral with code generation
- Backward compatible by design (field numbers)
- Good for polyglot environments
JSON Schema¶
- JSON format with schema validation
- Human-readable
- Larger payload size than Avro or Protobuf
- Good for debugging and web APIs
- Wide tooling support