Confluent Tableflow alternative — Confluent Tableflow vs Skippr
Confluent Tableflow is a Confluent Cloud feature that materializes Kafka topics as Apache Iceberg or Delta Lake tables. It reads Kafka segments in the Kora engine, writes Parquet, evolves schema, applies CDC semantics, compact files, and publishes into Snowflake Open Catalog, AWS Glue, or Databricks Unity Catalog. Storage can be Confluent-managed or your S3 / ADLS (Confluent says that path skips egress). Billing is topic-hours plus GB processed. Confluent's May 2026 TCO post lists 0.10 USD a topic-hour and 0.04 USD a GB, plus a 0.3 times compaction factor. Upsert mode also bills index GB processed. Enabling Iceberg and Delta on the same topic bills once. Kafka cluster eCKUs, ingress, storage, and (if you still use it) Connect are separate lines. Debezium CDC into the topic is a connector, not Tableflow. This is not a Streamhouse. There is no Iceberg ∪ WAL.
Skippr is an open Streamhouse you run as one Rust binary. Write skippr.yml (or the same thing in Python), discover, sync. You query live state over Iceberg ∪ WAL, and the history is ordinary Iceberg in your bucket. No topic-hour. ELT into a warehouse is one path, not the product.
| Feature | Skippr | Confluent Tableflow |
|---|---|---|
| Deploy | Single Rust binary, your VPC or on-prem | Confluent Cloud topic flag. Catalogs: Glue, Unity, Snowflake Open Catalog |
| Schema | In-stream evolution, sibling columns | Schema Registry plus Tableflow type conversion |
| Storage | Open Iceberg on Parquet you own | Iceberg or Delta from Kafka. Your bucket or Confluent-managed storage |
| CDC | Log-based; fails closed if the dest cannot honour | Materializes CDC already on the topic. Capture is Debezium or a producer |
| Query | skipprd query on Iceberg ∪ WAL; history in any Iceberg engine | After Tableflow publishes the table. Trino/Snowflake/Databricks read the catalog |
| Pricing | Free self-hosted engine | 0.10 USD/topic-hr + 0.04 USD/GB processed (Confluent TCO post). Kafka bill extra. |
What Confluent Tableflow is good at
A Kafka topic that already exists on Confluent Cloud and needs to show up as Iceberg without a Connect sink. That is the product. Compaction and catalog publish in the same feature is why some teams stop running a second Spark job. If the job is "this topic into this catalog," that is a real product.
Where the job is wider
Tableflow is a Kafka-to-table materializer. It is not a Streamhouse. There is no Iceberg ∪ WAL. There is no skipprd query on in-flight rows. CDC starts before Tableflow: a Debezium connector or an app still has to write the topic. Postgres is not a Tableflow source.
Cluster math is the ops. Topic-hours run while Tableflow is on. GB processed includes first materialization and compaction. Upsert index GB is a third line. Skippr will not replace a Confluent Cloud bus. Skippr also will not replace Tableflow on a topic that already lands Glue Iceberg. Debezium on Connect is a separate page.
If the job is "Confluent Kafka we already staff," Tableflow is the narrower tool. If the job is live SQL on Iceberg you run, Tableflow was never that.
Getting started
Install skipprd from the install guide, or pip install skippr. The three tabs write the same skippr.yml. Then discover, sync, and query.
skippr:
workspace: analytics
skipprd_el_storage_mode: local
pipelines:
orders:
data_source: data_sources.app_db
data_sink: data_sinks.lake
data_sources:
app_db:
Postgres:
host: db.internal
user: skippr_reader
password: ${APP_DB_PASSWORD}
database: app
tables: [orders, customers]
cdc_mode: snapshot_then_cdc
data_sinks:
lake:
AthenaIceberg:
warehouse: s3://my-iceberg-warehouse/
glue_database_name: analytics
athena_workgroup_name: primary
athena_results_s3_bucket: my-athena-results
region: us-east-1
schema_sink: schema_sinks.lake_schema
schema_sinks:
lake_schema:
AthenaIceberg:
warehouse: s3://my-iceberg-warehouse/
glue_database_name: analytics
athena_workgroup_name: primary
athena_results_s3_bucket: my-athena-results
region: us-east-1skipprd --workspace analytics --storage-mode local connect data-source postgres \
--pipeline orders \
--name app_db \
--host db.internal \
--user skippr_reader \
--password '${APP_DB_PASSWORD}' \
--database app \
--tables orders \
--tables customers \
--cdc-mode snapshot_then_cdc
skipprd connect data-sink athenaiceberg \
--pipeline orders \
--name lake \
--warehouse s3://my-iceberg-warehouse/ \
--glue-database-name analytics \
--athena-workgroup-name primary \
--athena-results-s3-bucket my-athena-results \
--region us-east-1
skipprd connect schema-sink athenaiceberg \
--pipeline orders \
--name lake_schemafrom skippr import (
Config,
DataSinkAthenaIceberg,
DataSourcePostgres,
DataSourcePostgresSourceCdcMode,
EnvRef,
LocalStorage,
Pipeline,
)
cfg = Config().workspace("analytics").storage(LocalStorage())
app_db = cfg.data_source(
"app_db",
DataSourcePostgres(
host="db.internal",
user="skippr_reader",
password=EnvRef("APP_DB_PASSWORD"),
database="app",
tables=["orders", "customers"],
cdc_mode=DataSourcePostgresSourceCdcMode.SNAPSHOTTHENCDC,
),
)
lake = cfg.data_sink(
"lake",
DataSinkAthenaIceberg(
warehouse="s3://my-iceberg-warehouse/",
glue_database_name="analytics",
athena_workgroup_name="primary",
athena_results_s3_bucket="my-athena-results",
region="us-east-1",
),
schema_sink="lake_schema",
)
cfg.pipeline("orders", Pipeline(data_source=app_db, data_sink=lake))
cfg.save("skippr.yml")export APP_DB_PASSWORD='your-postgres-password'
skipprd discover --pipeline orders
skipprd sync --pipeline orders --once
skipprd query "SELECT count(*) FROM analytics.orders"Which to choose
Choose Confluent Tableflow if you want Kafka topics materialized as Iceberg or Delta on Confluent Cloud, and the catalog after publish is enough.
Choose Skippr if you want one binary, live SQL, and Iceberg files that stay yours. Skippr will not enable Tableflow.
Install from Install. Connector and query reference live in Developer Docs. For optional onboarding in your VPC, Enterprise Jumpstart or Contact.
