Documentation Index

Fetch the complete documentation index at: https://kb.vastdata.com/llms.txt

Use this file to discover all available pages before exploring further.

Publishing Events to VAST Event Broker

Prev Next

VAST Event Broker collects events occurring to elements in VAST Element Store into Kafka event topics. VAST Event Broker is based on the VAST Database which allows consumers to query event topics via the various database APIs.

VAST Event Broker utilizes VAST proprietary implementation of the Kafka protocol, as detailed in Kafka Protocol Support.

The workflow is as follows:

  1. Configure VAST Event Broker. This is done by creating a view on a VAST Element Store path and enabling the ​Kafka​​ protocol on the view.

    Note

    Since VAST Event Broker requires a dedicated VIP pool, which must be designated from the available virtual IPs on the cluster, this configuration requires a ​cluster admin​​ manager user. If you want to provision of a VAST Event Broker for a tenant, a cluster admin user must create the VAST Event Broker view for the tenant.

  2. Create event topics using VAST VMS or with a Kafka client.

  3. Run S3 workload on the cluster to get the topics filled with events.

  4. Query events from VAST Event Broker topics  with a Kafka client or using a VAST Database connector.

  5. Monitor event traffic with VAST analytics.

  6. Protect event topics with VAST snapshots, global snapshot clones, and asynchronous replication

Kafka Protocol Support

The VAST implementation of the Kafka protocol supports a basic subset of the Kafka APIs to allow clients to publish and consume events from the VAST Event Broker.

VAST Event Broker supports:

  • Producer API

  • Consumer API

  • Consumer groups

  • Database queries on topics

  • Admin API:

    • Create topics

    • Get topic configuration ( describeConfigs )

    • Update topic configuration (alterConfigs)

    • Delete topics

    • Delete consumer groups

  • Topic compaction

  • SSL

The following Kafka capabilities are not supported:

  • Over-the-wire compression of messages

    Tip

    VAST compression of data is supported.

  • Automatic creation of topics

  • Transactions

The following limitations apply:

  • Producer API:

    • Messages are limited to 1MB.

    • In the event record, the key is limited to 126KB and the value is limited to 126KB.

    • Access to topics by UUID is not supported.

    • Idempotent producing is not supported.

    • Automatic creation of topics is not supported.

  • Consumer API:

    • No more than 256 consumer groups per view (broker)

    • The following is not supported:

      • Consumer group stickiness parameters (such as group.instance.id)

      • READ UNCOMMITTED isolation level

      • Cooperative rebalancing

      • Client rack awareness

      • Fetch sessions (only full fetch will be applied), delayed fetch parameters

      • Seek by time

  • Only one virtual IP pool can be associated with a Kafka-enabled view.

  • The amount of VAST Event Broker views that you can create on a VAST cluster, is limited by the maximum number of views supported by the cluster and by the maximum number of virtual IP pools (since each broker view requires a dedicated virtual IP pool). See VAST Cluster Scale Guidelines for details.

  • The amount of event topics that you can create on a VAST cluster, is limited by the maximum number of tables per VAST Database table (see VAST Cluster Scale Guidelines) and the overall amount of event topic partitions.

  • A topic can have up to 20,000 partitions. The number of partitions in a topic cannot be changed after the topic has been created. Up to 200,000 partitions are supported per VAST Event Broker view.

  • Event queries based on the topic partition are not supported.

  • When listing consumer groups, the response is limited to 256 groups per Kafka-enabled view.

  • VAST replication of consumer groups is not supported.

  • Event publishing and consuming operations, as well as topic management operations are not subject to VAST Protocol Auditing or Quality of Service (QoS).

Supported Kafka Clients

VAST Cluster supports Confluent Kafka Python client 2.4 - 2.8.

Configuring VAST Event Broker

Note

Since VAST Event Broker requires a dedicated VIP pool, which must be designated from the available virtual IPs on the cluster, this configuration requires a ​cluster admin​​ manager user. If you want to provision of a VAST Event Broker for a tenant, a cluster admin user must create the VAST Event Broker view for the tenant.


Complete these steps to configure VAST Event Broker:

  • Ensure that there is a virtual IP pool for VAST Event Broker.

  • Configure a user for VAST Event Broker.

  • Create a VAST Event Broker view.

  • (Optional) Set up authentication for users accessing the view.

  • (Optional) Set up mTLS authentication for the VAST Event Broker view.

  • (Optional) Set up authorization for users accessing the view.

Verifying a Virtual IP Pool for VAST Event Broker

With you cluster admin, verify that there is a virtual IP pool that can be used to access the event topics using the Kafka protocol. The pool must have the PROTOCOLS roles assigned.

If the VAST Event Broker view will be associated with a view policy that includes virtual IP pools, the pool specified as the Kafka pool must be one of the view policy pools.

Configuring a User for VAST Event Broker

Configure a user on the authentication provider attached to the tenant where VAST Event Broker will run so that the user has S3 bucket creation permissions and S3 access keys.

This user will be assigned as the bucket owner when creating a view for VAST Event Broker.

Creating a VAST Event Broker View

VAST Event Broker runs on a view that has Kafka protocol enabled.

Note

View nesting is not supported.

Follow the steps in Creating Views to create a VAST Event Broker view as follows:

  • Enter a Path to the location where event topics will be stored.

  • Enable the setting to Create directory for the view.

  • Specify a view Policy that enforces S3 Native security flavor.

  • Specify Kafka as the view's Protocol.

    Enabling the Kafka protocol automatically enables the S3 Bucket and Database protocols for the view.

    Adding the Kafka protocol to an existing view is not allowed.

  • Enter an S3 bucket name for the view.

  • Specify the user configured for VAST Event Broker as the Bucket owner (in the S3 tab in VAST Web UI).

  • Set the view to use the Virtual IP pool you created for VAST Event Broker (in the Kafka tab in VAST Web UI).

    Only one virtual IP pool can be associated with a VAST Event Broker view.

    Once the view has been created, the virtual IP pool cannot be replaced by another one (but it can be modified if needed).

Configuring User Authentication for the VAST Event Broker View

(Optional) Configure authentication of users accessing the Kafka-enabled view.

Users accessing a Kafka-enabled view can be authenticated against the VAST provider associated with the tenant using the PLAIN Simple Authentication and Security Layer (SASL) mechanism. SASL/PLAIN authentication is available on both encrypted (TLS) and non-encrypted connections.

To configure user authentication:

  • In VAST Web UI, specify the required authentication method in the Authentication Methods pane of the Kafka tab in view settings (Element Store -> Views -> choose to create or edit a view).

If you are going to use SASL/PLAIN authentication with TLS, ensure that the VAST cluster has been configured with a TLS certificate intended for use with Kafka-enabled views. To check or upload a Kafka TLS certificate and a key:

  • In VAST Web UI, choose Settings -> Certificates and in the Certificates for field, select Kafka.

The following limitations apply:

  • Active Directory/LDAP is not supported. The user must be defined as a VAST local user.

  • Only one Kafka TLS certificate can be uploaded per VAST cluster.

Configuring mTLS Authentication for the VAST Event Broker View

(Optional) Configure mutual TLS (mTLS) authentication between VAST Event Broker and event consumers, which allows the server to authenticate clients connecting to a Kafka-enabled view on the VAST cluster.

In multi-tenant environments, the VAST cluster can be configured to distinguish between mTLS certificates associated with particulars tenants, and thus to direct the IO to the intended tenant based on the mTLS certificate (instead of using the client IP or destination virtual IP for that purpose). This improves security while enforcing tenant isolation and tenant-level authorization for NFS clients.

Warning

If your cluster has a cluster-wide configuration of mTLS authentication for Kafka connections, Kafka mTLS certificates configured at the tenant level are not used, and the cluster authenticates Kafka clients based on the cluster-wide settings only.

If mTLS authentication is enabled, connections without a proper CA certificate are rejected.

The CA certificate can be tenant-specific or global (cluster-wide, accepted by all tenants).

Note

With VAST Event Broker mTLS in place, VAST Event Broker views hosted on multiple tenants can use the same virtual IP pool, since determination of the correct tenant for each client request will be done based on the information in the CA certificate.

You configure mTLS authentication for Kafka by adding an mTLS certificate in tenant settings.

After adding an mTLS certificate, you need to enable mTLS authentication for the VAST Event Broker view.

Prerequisites

Limitations
  • Revocation of an mTLS certificate by using CRL Distribution Points (CDP) is not supported.

Adding an mTLS Certificate for a Tenant

A tenant-level mTLS certificate must be unique across all tenants.

If the tenant is configured with a CA certificate and the client sends a certificate that is not signed by this CA (or a trust chain that does not provide for the signing), access is denied.

To add an mTLS certificate for a tenant:

  • In VAST Web UI:

    1. Open the Authentication settings for mTLS pane in tenant settings (Element Store -> Tenants -> choose to create or edit a tenant -> Advanced Protocol Settings tab).

    2. Click Add Certificate under Kafka Certificates or Kafka and NFS Certificates.

    3. Enter a CA certificate with a CRL file (optional) in the fields provided.

      Up to 2 CA certificates can be added per tenant.

Enabling mTLS Authentication for VAST Event Broker

To enable mTLS authentication for a VAST Event Broker view:

  • In VAST Web UI, select the Require mTLS option in view settings (Element Store -> Views -> choose to create or edit a view -> select Kafka protocol for the view -> Kafka tab -> Authentication Methods pane).

Configuring User Authorization for the VAST Event Broker View

(Optional) Configure authorization of users accessing the Kafka-enabled view.

Only explicitly allowed operations can be performed.

  • Enable authorization for the Kafka view:

    • In VAST Web UI, toggle the Enable authorization option on in view settings (Element Store -> Views -> choose to create or edit a view -> Kafka tab -> Authentication Methods pane).

  • Add Kafka-related actions to user identity policies.

Managing Event Topics

You create, view, modify and delete event topics similar to VAST Database tables. When you create a VAST Event Broker view, VAST Cluster automatically creates an associated VAST database with a schema labelled Kafka-Compatible Broker Topics. Under this schema, you can create and manage topics where events will be recorded.

Creating a Topic in VAST Web UI

To create a topic in VAST Web UI:

  1. In the left navigation menu, choose DataBase -> VAST Database to open a list of databases available on the cluster.

  2. Click an arrow on the left to the database named after your Kafka-enabled view and then click Kafka-Compatible Broker Topics under the database name.

  3. Click the Add Topic button on the right to create a new topic.

  4. In the Create Topic dialog, complete the following required fields:

    Topic Name

    Enter a name for the topic.

    Number of partitions 

    Enter the number of partitions for the topic.

    Each topic can hold up to 1000 partitions. The number of partitions in a topic cannot be changed after the topic has been created.

    Note

    The number of partitions can be set only when creating a topic. It cannot be modified by editing an existing topic.

    Under Data Preservation and Efficiency:

    Retention Period 

    Specify the amount of time to keep an event record in the topic. When the retention period for a record expires, the records is deleted from the topic.

    The default retention period is seven days. The minimum allowed retention period is 6 hours. A value of -1 means no retention period.

    Compaction

    If this flag is set, VAST Cluster keeps only the latest record version for each key in the partition log. Any previous versions of the record are deleted.

    Note

    Compaction is performed asynchronously in the background. At some point in time, duplicate keys may exist.

    Minimum compaction lag

    The minimum time during which a message can stay non-compacted in the partition log.

    Tombstone Retention Period

    The period during which tombstone records can be kept in a topic for which compaction is enabled.

    Under Advanced options -> Timestamp source:

    Time event is created (producer)

    Sets the event timestamp based on the time when the event was encountered at the event producer.

    Time event is logged (server)

    Sets the event timestamp based on the time when the event record was added to the log at the event broker.

    Under Advanced options -> Event time validation period:

    Infinity

    For Time event is created (producer) timestamps, specifies that any difference between the producer time and the server time is acceptable, e.g. the message timestamp can be earlier or later than the broker timestamp for any amount of time.

    Define Manually

    For Time event is created (producer) timestamps, specifies the acceptable difference between the producer time and the server time:

    • Not before: Determines how much earlier the message timestamp can be than the broker timestamp. If this value is exceeded, the message is rejected.

    • Not after: Determine how much later the message timestamp can be than the broker timestamp. If this value is exceeded, the message is rejected.

    Under Advanced options -> Topic max message size:

    Max size

    The maximum allowed size for a message in megabytes.

    If set to a value above 5MB, topic compaction is not performed, and database queries on the topic are not supported.

  5. Click Create.

Modifying a Topic in VAST Web UI

To modify a topic in VAST Web UI:

  1. In the left navigation menu, choose DataBase -> VAST Database to open a list of databases available on the cluster.

  2. Click an arrow on the left to the database named after your Kafka-enabled view and then click Kafka-Compatible Broker Topics under the database name.

  3. Click on the the topic you want to edit so that it is displayed in the central pane. Then click the Edit button on the top right.

  4. In the Create Topic dialog, make changes as needed. See Creating a Topic in VAST Web UI for a description of each field.

  5. Click Create.

Granting Kafka Permissions in an Identity Policy

You grant permissions for Kafka-related objects by listing operations that a user is allowed or prohibited to perform in the user's identity policy.

By default, if no ACL is found, the operation is allowed for any user. If you want to alter this behavior, contact VAST Support.

The following Kafka operations are supported:

  • For a topic:

    • Read

    • Write

    • AlterConfigs

    • Create

    • Delete

    • Describe

    • DescribeConfigs

  • For a consumer group:

    • Read

    • Delete

    • Describe

  • For a Kafka cluster (the Kafka-enabled view):

    • Alter

    • AlterConfig

    • ClusterAction

    • Create

    • Describe

    • DescribeConfigs

For example, the following identity policy allows the user to read and write to the topic, but prohibits topic creation and deletion:

"Version": "2012-10-17",
"Statement": [
  {
    "Sid": "Aaa__gggg",
    "Action": "KafkaRead",
    "Effect": "Allow",
    "Resource": "vast:kafka:topic:kafka-pppp:ddd_0"
  },
  {
    "Sid": "Aaa__ssss",
    "Action": "KafkaWrite",
    "Effect": "Allow",
    "Resource": "vast:kafka:topic:kafka-pppp:ddd_0"
  },
  {
    "Sid": "Aaa__dddd",
    "Action": "KafkaCreate",
    "Effect": "Deny",
    "Resource": "vast:kafka:topic:kafka-pppp:ddd_0"
  },
  {
    "Sid": "Aaa__cccc",
    "Action": "KafkaDelete",
    "Effect": "Deny",
    "Resource": "vast:kafka:topic:kafka-pppp:ddd_0"
  },
]

Managing Topics, Producing and Consuming Events with a Kafka Client

Prior to using Kafka APIs, ensure that the prerequisites described in Configuring VAST Event Broker are met.

The following examples use a Kafka client that can be installed with:  pip install kafka-python.

In the examples, you need to supply a list of Kafka bootstrap server IPs. These are the IPs that a Kafka client uses to connect to the cluster. It is recommended to specify three of the virtual IPs from the virtual IP pool assigned to the VAST Event Broker view.

Create a Topic

from kafka.admin import KafkaAdminClient, NewTopic
BOOSTRAP_SERVERS = "<comma-separated list of IPs>"
topic_name = #
# Kafka Admin Configuration
admin_client = KafkaAdminClient(
    bootstrap_servers=[BOOSTRAP_SERVERS],
    client_id='python-admin-client'
)
topic_name = topic_name
num_partitions = 2
replication_factor = 1
topic = NewTopic(
    name=topic_name,
    num_partitions=num_partitions,
    replication_factor=replication_factor
)
try:
    # Create the topic
    admin_client.create_topics(new_topics=[topic], validate_only=False)
    print(f"Topic '{topic_name}' created successfully with {num_partitions} partitions and replication factor {replication_factor}.")
except Exception as e:
    print(f"Error creating topic: {e}")
finally:
    admin_client.close()

List Topics

BOOTSTRAP_SERVER = "<comma-separated list of IPs>"
from kafka.admin import KafkaAdminClient
# Define the Kafka broker (adjust the host/port as needed)
# Create an admin client
admin_client = KafkaAdminClient(bootstrap_servers=BOOTSTRAP_SERVER)
# Fetch the list of topics
topics = admin_client.list_topics()
# Print the list of topics
print("Kafka Topics:", topics)
# Close the admin client
admin_client.close()

Write to a Topic

from kafka import KafkaProducer
import json
BOOSTRAP_SERVERS = "<comma-separated list of IPs>"
producer = KafkaProducer(bootstrap_servers=BOOSTRAP_SERVERS)
for i in range (100,2500):
    key = str(i)
    message = {"name": "vast", "id": i}
    producer.send(topic_name, key=key.encode("utf-8") , value=json.dumps(message).encode('utf-8'))
producer.flush()
print("Message sent to Kafka topic")

Read from a Topic

BOOSTRAP_SERVERS = "<comma-separated list of IPs>"
from kafka import KafkaConsumer
consumer = KafkaConsumer(
    topic_name,
    bootstrap_servers=[BOOSTRAP_SERVERS],
    auto_offset_reset='earliest',
    group_id='your-consumer-group-name'
)
for message in consumer:
    print(f"Received message: {message.value.decode('utf-8')}")

Delete a Topic

from kafka.admin import KafkaAdminClient, NewTopic
# Define the Kafka broker
BOOTSTRAP_SERVER = "<comma-separated list of IPs>"
TOPIC_TO_DELETE = "my_topic"  # Change this to the topic you want to delete
# Create an admin client
admin_client = KafkaAdminClient(bootstrap_servers=BOOTSTRAP_SERVER)
# Delete the topic
try:
    admin_client.delete_topics([TOPIC_TO_DELETE])
    print(f"Topic '{TOPIC_TO_DELETE}' deleted successfully.")
except Exception as e:
    print(f"Failed to delete topic '{TOPIC_TO_DELETE}': {e}")
# Close the admin client
admin_client.close()

Querying Events from Topics using VAST Database Connectors

VAST Event Broker topics can be queried through the VAST Database API, and also using VAST Database connectors (e.g. the connectors for Trino and Spark).

The following Trino example shows the schema (kafka_topics) of the VAST Database used to store event topics, among other schemas on the VAST cluster:

trino> show schemas in vast;
                     Schema                      
-------------------------------------------------
 information_schema                              
 kafka2/kafka_topics                             
 system_schema                                   
 vast-audit-log-bucket/vast_audit_log_schema     
 vast-big-catalog-bucket/vast_big_catalog_schema 
(5 rows)

The following Trino example shows topics within the kafka_topics schema:

trino> show tables in vast."kafka2/kafka_topics";
         Table          
------------------------
 docker-connect-configs 
 docker-connect-offsets 
 docker-connect-status  
 my-new-topic           
 myfirsttopic           
 newtopic               
 streaming-topic                     
(7 rows)

Monitoring Kafka Performance with VAST Analytics

VAST Cluster provides analytic reports that show latency and bandwidth for produced and fetched events and messages per VAST Event Broker view and per CNode.

To access Kafka-related analytics in VAST Web UI, go to Analytics -> Analytics -> Predefined Analytics tab, set the View or CNode filter and select one of the reports containing the word Kafka.

Data Protection Capabilities for Event Topics

The following data protection capabilities are supported for VAST Event Broker topics:

  • VAST asynchronous replication and failover

    The replicated topics are read-only at the destination peer. In case of a failover, the destination peer becomes the one hosting the topics to which events are produced.

  • Snapshots and global snapshot cloning

    A clone can be created from either local or remote snapshots.

The following rules and limitations apply:

  • The Kafka-enabled view needs to be manually created and associated with a virtual IP pool at the destination peer. The pool must have the same name as the one at the source peer.

  • Fast restore of a protected path containing a Kafka-enabled view is not allowed.

  • Consumer group offsets are not replicated.

Parsing Kafka Events into a VAST Database Table

Overview of Kafka Event Parsing

Information in Kafka event messages can be parsed and saved in a VAST database table that can then be queried using any of the query methods available for VAST database tables.

You configure parsing by creating or selecting a VAST database table that will store parsed Kafka event data, and then selecting the specific fields to be parsed from the Kafka events. Columns corresponding to the these fields are added to the table (if not already present), and all subsequent events are parsed for these fields.

You can view statistics for parsed Kafka events using custom analytics in the Analytics page of the VAST Web UI.

Required S3 Permissions for Kafka Event Parsing

In order to configure or modify event parsing configurations in the VAST Database, these S3 permissions are required:

  • s3:TabularCreateBlobExpansion

  • s3:TabularAlterBlobExpansion

  • s3:TabularDropBlobExpansion

  •  s3:TabularGetBlobExpansion

These are described in Managing Permissions for Accessing VAST Tabular Databases

Parsing Kafka Events into a VAST Database Table using the VAST Web UI

  1. Navigate to the Database page, and select the Kafka broker and topic containing the events to be parsed. The Kafka broker is implemented as a VAST Database.

  2. Click Add Blob Expansion.

  3. In the Add Blob Expansion dialog, in the General Configuration section, select the target schema and table. This is the table that will store parsed events information. This must be an existing table in a VAST Database. To create a new table, see Creating a Table using the VAST Web UI.

  4. In the Table Columns section, enter the name of a field in the Kafka event, and select its type. The name and type must match the name of the field, and its type, in the event message, including case.

    You can enter structured fields, to match structured fields. Select struct as the Column type, and the select the individual struct, array, or map types within the structure.  You can also include structures within structures.             

  5. Click Add Column to Table. The fields appear in the Expansion Columns list.

  6. Click Add New Column, and repeat the above steps, to add additional fields, as necessary.

  7. Optionally, select any of these options for the parsing:

    Flatten nested structures

    Convert structures and nested structures into individual fields.

    For example, the structure

    {
    "user": {
        "id": 1,
        "name": "John Smith"
    }
    }

    is parsed into columns user_id, and user_name.

    Copy original message

    Copies the original Kafka event message to the target table.

    Count excessive values in source

    Indicates the number of columns in the message that were not parsed (since they were not selected to be parsed). For example, for a message with 1000 fields, of which 150 are selected for parsing, the value is 850.

    Count missing values in source

    Indicates the number of selected fields that were not found in the message. For example, if only 10 fields are found in the message, of 15 fields selected for parsing, the value is 5.

  8. Click Add. This saves the parsing configuration, and enables parsing of events from the topic.

Adding Fields for Parsing of Kafka Events using the VAST Web UI

  1. Navigate to the Database page, and select the Kafka broker and topic.

  2. In the action menu (Actiion-menu-symbol.png) on the right, select Add Columns.

  3. In the Table Columns section, enter the name of a field in the Kafka event, and select its type. The name and type must match the name of the field, and its type, in the event message, including case.

    You can enter structured fields, to match structured fields. Select struct as the Column type, and the select the individual struct, array, or map types within the structure.  You can also include structures within structures.             

  4. Click Add Column to Table. The fields appear in the Expansion Columns list.

  5. Click Add New Column, and repeat the above steps, to add additional fields, as necessary.

  6. Optionally, select from these advanced options:

    Copy original message

    Copies the original Kafka event message to the target table.

    Count excessive values in source

    Indicates the number of columns in the message that were not parsed (since they were not selected to be parsed). For example, for a message with 1000 fields, of which 150 are selected for parsing, the value is 850.

    Count missing values in source

    Indicates the number of selected fields that were not found in the message. For example, if only 10 fields are found in the message, of 15 fields selected for parsing, the value is 5.

  7. Click Add. This updates the parsing configuration.

Removing Fields from Parsing of Kafka Events using the VAST Web UI

  1. Navigate to the Database page, and select the Kafka broker and topic.

  2. In the action menu (Actiion-menu-symbol.png) on the right, select Blob Expansion and then Remove Columns.

  3. In the Remove Columns dialog, the Expansion Columns section lists all fields that were selected for parsing (columns in the target table). Select the ones to be removed.

  4. In the Extra Columns section, select any of the other parsing options to be disabled.

  5. Click Remove. This updates the parsing configuration.

Parsing Kafka Events into a VAST Database Table using the Python SDK (PySDK)

This example illustrates how parsing can be configured for a Kafka topic, using the VAST PySDK.

import pyarrow as pa
import vastdb  # pip install vastdb  (requires Python 3.10)
from vastdb.table import BlobExpansionConfig, ExpansionFormat

# Connection info
kafka_bucket  = "my_kafka_bucket"
kafka_schema  = "kafka_topics"      # the schema Kafka topics live under
topic_name    = "my_topic"          # source table = Kafka topic name
target_schema = "expanded_data"     # different schema, same bucket
target_table  = "my_expanded_table"

# NOTE: the source table (topic_name) and its Kafka topic must be created beforehand

# 1. Connect
session = vastdb.connect(access_key, secret_key, endpoint)

# 2. Create the target schema (different schema, same bucket)
with session.transaction() as tx:
    tx.bucket(kafka_bucket).create_schema(target_schema)

# 3. Define what the expanded blob looks like
expansion_schema = pa.schema([
    pa.field("event_type", pa.string()),
    pa.field("id",  pa.int64()),
    # ... any fields the JSON/blob contains
])

# 4. Create the target table in the target schema
with session.transaction() as tx:
    tx.bucket(kafka_bucket).schema(target_schema).create_table(
        target_table, expansion_schema, sorting_key=[]
    )

# 5. Create the blob expansion (links source blob column → target table)
with session.transaction() as tx:
    be = tx.bucket(kafka_bucket).schema(kafka_schema).table(topic_name).create_blob_expansion(
        expansion_schema=expansion_schema,
        target_table_name=target_table,
        target_table_schema=target_schema,   # required: target is in a different schema
        source_column_name="value",
        config=BlobExpansionConfig(
            expansion_format=ExpansionFormat("json"),
            copy_source_column=False,
            flatten_path=False,
            flatten_delimiter="__",
        ),
    )

# 6. Add a column to the blob expansion
columns_to_add = pa.schema([
    pa.field("user_id", pa.string()),
])
with session.transaction() as tx:
    be = tx.bucket(kafka_bucket).schema(kafka_schema).table(topic_name).blob_expansion("value")
    be.add_columns(columns_to_add=columns_to_add)

# 7. Remove a column from the blob expansion
columns_to_remove = pa.schema([
    pa.field("id", pa.int64()),
])
with session.transaction() as tx:
    be = tx.bucket(kafka_bucket).schema(kafka_schema).table(topic_name).blob_expansion("value")
    be.drop_columns(columns_to_remove=columns_to_remove)

# 8. Drop the blob expansion entirely
with session.transaction() as tx:
    tx.bucket(kafka_bucket).schema(kafka_schema).table(topic_name).blob_expansion("value").drop()