Explicit Topic-Subject Associations
An explicit topic-subject association links a Kafka topic directly to a Schema Registry subject.
Clients use a subject name strategy to decide which subject to register a topic’s schema under and read it from:
Strategy |
Association type |
How it finds the subject |
Subject name |
When it applies |
|---|---|---|---|---|
|
Explicit |
Looks up the subject associated with the topic |
The subject the association points to |
The default on client library versions that support it. If the topic has no
association, it falls back to |
|
Legacy implicit |
Derives the name from the topic |
|
The default on earlier client library versions, and the default fallback. All messages in a topic use the same schema. |
|
Legacy implicit |
Derives the name from the record |
The fully qualified record name |
A topic carries more than one record type, and you want compatibility checked per record type across all topics. |
|
Legacy implicit |
Derives the name from the topic and the record |
|
A topic carries more than one record type, and you want compatibility checked per record type within each topic. |
The strategies other than AssociatedNameStrategy derive the subject name
from the topic or the record each time a client runs. Nothing records which
subject a topic uses, and nothing stops someone from deleting that subject
while the topic still uses it. An association records the relationship and
prevents deletion of the subject while a topic uses it.
For the client library versions that support AssociatedNameStrategy, see
Supported client library versions. For details on the other legacy
strategies, see Subject name strategy.
Explicit associations introduce these distinct architectural patterns:
Topic-native schemas, also called native schemas, where a schema is strictly bound to a single topic. The schema exists only while the topic exists, like a table schema in a database.
Shared schemas, where a single schema can be explicitly linked across more than one topic. Schema Registry subjects already work this way. The subject stays when you remove the association.
A topic created with a schema gets a native schema, and a topic associated
with an existing subject gets a shared schema. The API reports each
association’s lifecycle, STRONG for native and WEAK for shared. See
Key concepts.
Create, change, and delete associations by setting the topic configurations
confluent.key.association and confluent.value.association. Use the
Kafka Admin API, for example the createTopics and
incrementalAlterConfigs requests. Don’t call the Schema Registry Associations API to
write associations. Schema Registry sets each association’s lifecycle value based on
how you create the topic. You don’t specify it. You can call the Schema Registry
Associations API to read associations.
Key concepts
Term |
Meaning |
|---|---|
Subject |
The named container in Schema Registry where a schema and its versions are
registered. For example, |
Association |
The link between a topic and a subject. It has a lifecycle of
|
Native schema |
A schema owned by one topic. It has a lifecycle of |
Shared schema |
A schema that more than one topic can use. It has a lifecycle of
|
|
The subject name strategy that clients use by default on supported
client library versions. It uses a topic’s association to find the
subject, and falls back to |
Prerequisites
Brokers with
confluent.topic.subject.association.enableset totrue. Brokers accept association settings only with that setting.Client libraries that support
AssociatedNameStrategy. See Supported client library versions.
The following examples use three resources:
orders: a topic with its own nativeOrderschema.Customer: a shared schema registered on its own.customer-signups: a topic associated with the sharedCustomerschema.
Create a topic with a native schema
Create the topic and its schema in one request through the Kafka API. The schema belongs to the topic. It evolves with the topic, and Schema Registry deletes it when you delete the topic.
To create the schema with the topic, send a createTopics request that sets
confluent.value.association. For a key schema, set
confluent.key.association. The value is a JSON object with schemaType
and schema.
By default, Schema Registry names the subject <topic_name>-value and places it in the
schema context :.<cluster_id>:, where <cluster_id> is the 22-character
Kafka cluster ID, like MkU3OEVBNTcwNTJENDM2Qk. To choose a different name,
set subject in the JSON object.
Note
Deleting a topic that has a native association also deletes its subject and every schema version.
These examples use the Order schema:
{
"type": "record",
"name": "Order",
"namespace": "com.example.avro",
"fields": [
{ "name": "orderId", "type": "string" },
{ "name": "amount", "type": "double" }
]
}
The following example creates the orders topic and registers its Order
schema as a native schema:
Properties props = new Properties();
props.put("bootstrap.servers", "<kafka-endpoint>");
try (AdminClient adminClient = AdminClient.create(props)) {
NewTopic topic = new NewTopic("orders", 1, (short) 1);
Map<String, String> valueAssociation = new HashMap<>();
valueAssociation.put("schemaType", "AVRO");
valueAssociation.put("schema",
"{\"type\":\"record\",\"name\":\"Order\","
+ "\"namespace\":\"com.example.avro\","
+ "\"fields\":[{\"name\":\"orderId\",\"type\":\"string\"},"
+ "{\"name\":\"amount\",\"type\":\"double\"}]}");
Map<String, String> topicConfig = new HashMap<>();
topicConfig.put("confluent.value.association",
new ObjectMapper().writeValueAsString(valueAssociation));
topic.configs(topicConfig);
adminClient.createTopics(Collections.singletonList(topic)).all().get();
}
Remove an association
To remove a shared association, unlink the topic. The shared subject and its
schema stay in Schema Registry, and other topics keep using them. After you remove the
association, the topic’s confluent.value.association configuration
returns to its default empty value. Schema Registry no longer lists the association
for the topic.
You can’t remove a native association on its own. Schema Registry removes it when you delete the topic, which also deletes the subject.
To remove a key association, use confluent.key.association for the
configuration name. To unlink the topic, send a DELETE operation on the
configuration:
ConfigResource topic =
new ConfigResource(ConfigResource.Type.TOPIC, "customer-signups");
AlterConfigOp op = new AlterConfigOp(
new ConfigEntry("confluent.value.association", null),
AlterConfigOp.OpType.DELETE);
adminClient.incrementalAlterConfigs(Map.of(topic, List.of(op))).all().get();
Query associations
Use the Schema Registry Associations API to find the subjects associated with a topic or the topics associated with a subject.
Look up by subject
Send this request to list the topics associated with the Customer
subject:
GET /associations/subjects/Customer
Example response:
[
{
"subject": "Customer",
"guid": "7a3c1f52-2d4e-4b8a-b6c1-9e0f5a1d2c33",
"resourceName": "customer-signups",
"resourceNamespace": "MkU3OEVBNTcwNTJENDM2Qk",
"resourceId": "ZyXwVuTsRqPoNmLkJiHgFe",
"resourceType": "topic",
"associationType": "value",
"lifecycle": "WEAK",
"createTs": 1719000000000,
"updateTs": 1719000000000
}
]
Look up by topic
Send this request to list the subjects associated with the orders topic:
GET /associations/resources/{cluster_id}/orders
{cluster_id} is the Kafka cluster ID.
Example response:
[
{
"subject": ":.MkU3OEVBNTcwNTJENDM2Qk:orders-value",
"guid": "5f4d6d3e-8b1a-4c2e-9a7f-1c9e8d2b3a4f",
"resourceName": "orders",
"resourceNamespace": "MkU3OEVBNTcwNTJENDM2Qk",
"resourceId": "AbCdEfGhIjKlMnOpQrStUv",
"resourceType": "topic",
"associationType": "value",
"lifecycle": "STRONG",
"createTs": 1719000000000,
"updateTs": 1719000000000
}
]
createTs and updateTs are epoch milliseconds. guid is an internal
identifier, not a schema ID.
Filters and paging
Both lookups accept these optional query parameters:
Parameter |
Values |
Example |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
Where to start. Defaults to |
|
|
The most results to return. Defaults to |
|
An empty list means that no association matches your filters. A change to an association can take a few seconds to appear in lookup results.
Delete topics and subjects
Action |
Native schema ( |
Shared schema ( |
|---|---|---|
Delete the topic |
Deletes the association, the subject, and all schema versions. |
Removes the association. The subject and its schema stay. |
Delete the subject |
Blocked while the topic exists. |
Blocked while any topic has an association. Unlink the topics first. |
Use associations with clients
On a supported client library version, AssociatedNameStrategy is the
default subject name strategy, and you don’t need to configure anything.
The strategy finds the topic’s associated subject first, and falls back to
TopicNameStrategy when the topic has no association. Existing
applications keep working unchanged. The same producer and consumer code
works for native, shared, and unassociated topics.
Supported client library versions
AssociatedNameStrategy is the default from the versions in this table.
Earlier versions default to TopicNameStrategy and don’t use associations to
find the subject.
Language |
Client library |
Earliest supported version |
|---|---|---|
Java Client |
Confluent serializers ( |
Requires |
Python |
|
2.14.0 |
Go |
|
2.14.0 |
Node.js |
|
1.9.0 |
.NET |
|
2.14.0 and 0.1.3 |
Caution
A producer on an earlier client library version doesn’t read
associations. It builds the subject name from the topic name. For the
topic customer-signups, it registers the schema under
customer-signups-value and not the associated subject Customer. A
producer that registers schemas automatically, the default, creates that
second subject. You end up with two subjects for the same schema. To avoid
this, upgrade the client library to a version in the preceding table.
Broker-side schema ID validation
Broker-side schema ID validation is an optional topic setting. When it’s on, the broker checks that the schema ID in each message is valid for the subject that the topic uses.
The broker uses AssociatedNameStrategy by default and finds the subject
through the topic’s association. If the topic has no association, the broker
falls back to TopicNameStrategy. You don’t need to configure anything on
the topic. For details, see AssociatedNameStrategy.
Fallback strategy
If a topic has no association, AssociatedNameStrategy falls back to
TopicNameStrategy by default. To choose the fallback, set
subject.name.strategy.fallback.type on the client:
Value |
Fallback |
|---|---|
|
|
|
|
|
|
|
No fallback |
Serialization fails with an error if the fallback is NONE and the topic has
no association, or if the topic has more than one associated subject for the
same key or value. Deserialization fails when the deserializer needs to
resolve a subject. Examples include use.latest.version,
use.latest.with.metadata, and migration rules. A deserializer that reads
only the schema ID embedded in the message isn’t affected. Which deserializer
settings resolve a subject varies by client library.
Replication across clusters
Cluster Linking doesn’t replicate associations. To replicate a topic that has an association, use Cluster Linking to mirror the topic and Schema Linking to replicate its schema. Then create the associations that exist on the source topic manually on the destination topic.