> ## Documentation Index
> Fetch the complete documentation index at: https://docs.streamnative.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Use Kafka Schema References

> Compose schemas from other registered schemas so shared types are defined once, and understand how references affect deletion.

A schema reference lets one schema point at another registered schema instead of inlining its
definition. Define a shared `Address` type once and reference it from `Customer`, `Order`, and
`Invoice`, and a change to `Address` propagates instead of drifting across three copies.

The StreamNative Kafka Schema Registry supports references for all three formats, including
references that themselves contain references.

## Register a referenced schema

Register the shared schema first:

```shell theme={null}
curl -u "any-user:$API_KEY" \
  -X POST -H "Content-Type: application/vnd.schemaregistry.v1+json" \
  --data '{"schemaType": "AVRO", "schema": "{\"type\":\"record\",\"name\":\"Address\",\"namespace\":\"com.acme\",\"fields\":[{\"name\":\"street\",\"type\":\"string\"},{\"name\":\"city\",\"type\":\"string\"}]}"}' \
  https://<schema-registry-url>/subjects/com.acme.Address/versions
```

Then register the schema that uses it, listing the reference:

```shell theme={null}
curl -u "any-user:$API_KEY" \
  -X POST -H "Content-Type: application/vnd.schemaregistry.v1+json" \
  --data '{
    "schemaType": "AVRO",
    "schema": "{\"type\":\"record\",\"name\":\"Customer\",\"namespace\":\"com.acme\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"address\",\"type\":\"com.acme.Address\"}]}",
    "references": [
      {"name": "com.acme.Address", "subject": "com.acme.Address", "version": 1}
    ]
  }' \
  https://<schema-registry-url>/subjects/customers-value/versions
```

Each entry in `references` has three fields:

| Field     | Meaning                                                                                                                                               |
| --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name`    | How the referencing schema names the type. For Avro, the fully qualified record name; for Protobuf, the import path; for JSON Schema, the `$ref` URL. |
| `subject` | The subject holding the referenced schema.                                                                                                            |
| `version` | The version within that subject.                                                                                                                      |

## Per-format syntax

**Avro**—reference a record by its fully qualified name, as in the example above. The `name` in the
reference entry is that fully qualified name.

**Protobuf**—reference through an `import` statement. The `name` is the import path:

```protobuf theme={null}
syntax = "proto3";
package com.acme;

import "com/acme/address.proto";

message Customer {
  string name = 1;
  Address address = 2;
}
```

```json theme={null}
"references": [
  {"name": "com/acme/address.proto", "subject": "com.acme.Address", "version": 1}
]
```

**JSON Schema**—reference through `$ref`, with the `name` matching the `$ref` value:

```json theme={null}
{
  "type": "object",
  "properties": {
    "address": {"$ref": "address.json"}
  }
}
```

```json theme={null}
"references": [
  {"name": "address.json", "subject": "com.acme.Address", "version": 1}
]
```

<Warning title="External URLs are rejected">
  A JSON Schema `$ref` that points at an external URL is rejected. Every reference must resolve to a
  schema registered in this registry.
</Warning>

## Find what references a schema

```shell theme={null}
curl -u "any-user:$API_KEY" \
  https://<schema-registry-url>/subjects/com.acme.Address/versions/1/referencedby
```

The response is an array of schema IDs. Resolve each one with `GET /schemas/ids/{id}/subjects` to see
which subjects hold it.

## References block deletion

You cannot delete a schema while another schema references it. The attempt returns error code
**42206**.

Delete the referencing schemas first, or use `referencedby` to find them. This applies to soft and
hard deletes alike, and it's the most common reason a delete you expected to succeed doesn't.

## Evolving referenced schemas

A reference pins a specific version. Registering `Address` version 2 does **not** change what
`Customer` resolves to—it still points at version 1.

To adopt the new version, register a new version of the referencing schema with the reference updated
to `"version": 2`. That new version goes through the referencing subject's own compatibility check,
so a breaking change to `Address` surfaces as a failure on `customers-value` rather than silently
altering it.

<Tip>
  Because references pin versions, a shared type can evolve without forcing every consumer to move at
  once. That's the main reason to use references rather than inlining.
</Tip>

## Next steps

<CardGroup cols={2}>
  <Card title="Serializers and deserializers" icon="code" href="/kafka/governance/sr/fundamentals/serdes">
    How the client registers and resolves schemas.
  </Card>

  <Card title="Evolution and compatibility" icon="code-compare" href="/kafka/governance/sr/fundamentals/schema-evolution">
    How compatibility checks treat a changed reference.
  </Card>
</CardGroup>
