Skip to main content
This guide shows how to read data from external Apache Iceberg tables in RisingWave. Use it when your Iceberg tables are managed by external systems and you want to treat them as a streaming source for real-time processing. You can ingest data from Iceberg tables using two approaches:
  1. Continuous ingestion (default): Create an Iceberg source with the CREATE SOURCE statement. Sources ingest append-only data by default, or can opt in to streaming updates for supported tables written by RisingWave.
  2. Periodic full reload: Create an Iceberg table with refresh_mode = 'FULL_RELOAD' for scheduled full table refreshes. Note that you must use CREATE TABLE (not CREATE SOURCE), and data will only be loaded after you trigger a refresh—either manually or via the configured schedule.
After the source or table is created, you can run ad hoc queries against it or maintain materialized views for continuous analytics.

Prerequisites

  • An existing Apache Iceberg table managed by external systems.
  • Access credentials for the underlying storage system (e.g., S3 access key and secret key).
  • Network connectivity between RisingWave and your storage system.
  • Knowledge of your Iceberg catalog type and configuration.

Continuous ingestion with CREATE SOURCE

Modes and limitations

  • Append-only ingestion is the default. In this mode, RisingWave uses a hidden, system-generated _row_id column, and you cannot define a primary key.
  • Streaming updates are opt-in. Set streaming_updates = 'true' and specify a primary key to ingest updates and deletes from supported RisingWave-written tables.
  • Column definitions are not allowed for Iceberg sources. RisingWave automatically infers the schema from the Iceberg table metadata. Do not specify column names or types in the CREATE SOURCE statement. In streaming update mode, specify only the PRIMARY KEY constraint before the WITH clause.

Basic connection example

The following example creates a source for a table in S3 using AWS Glue as the catalog:
When you read from an external Iceberg table, RisingWave automatically derives column names and data types from the Iceberg table metadata. Use the DESCRIBE statement to view the schema:

Parameters

You also need to specify catalog and object storage parameters in the CREATE SOURCE statement. Because these parameters are shared across all Iceberg objects—sources, sinks, and internal Iceberg tables—they are documented separately. For details on how data types are mapped between RisingWave and Iceberg, see the Data type mapping guide.

Source example

For a REST catalog:

Stream updates and deletes

Set streaming_updates = 'true' to ingest an initial snapshot and then continuously propagate inserts, updates, and deletes. You can use either CREATE SOURCE or CREATE TABLE; in both cases, specify a logical primary key whose columns uniquely identify the rows written by the upstream RisingWave PK-index sink.
The schema is still inferred from Iceberg. The PRIMARY KEY clause declares the logical key; do not define column names or types in the statement.
Streaming update ingestion is intended only for Iceberg tables produced by a RisingWave PK-index writer, such as an upsert Iceberg sink. It is not a general CDC reader for tables written by arbitrary Iceberg writers.
The mode supports Iceberg V2 tables with file-scoped Parquet position deletes and Iceberg V3 tables with deletion vectors. Equality deletes are not supported. Without streaming_updates = 'true', existing append-only, batch, and refresh behavior remains unchanged. Keep the snapshots, manifests, data files, and delete artifacts needed by lagging or recovering jobs. If required history is expired, or if RisingWave detects a rollback, changed table identity or schema, equality deletes, or another unsupported artifact, the streaming job fails instead of silently loading a new snapshot. The following features are not supported with streaming_updates = 'true':
  • Shared sources
  • Refresh, including refresh_mode = 'FULL_RELOAD'
  • INCLUDE columns and source watermarks
  • Source rate limiting
  • Streaming time travel queries
You cannot change streaming_updates with ALTER. Create a new source or table to change modes. Updates are applied as a delete phase followed by an insert phase. Downstream results converge to the Iceberg table contents, but intermediate states between these phases can be visible; the mode does not provide atomic snapshot switching.

Periodic full reload with CREATE TABLE

Added in v2.7.0. It is currently in technical preview stage.
For batch-style workloads where you need to periodically reload an entire Iceberg table, you can create a table with refresh_mode = 'FULL_RELOAD'. This mode is useful when:
  • The external Iceberg table supports mutable data (updates and deletes).
  • You need a point-in-time snapshot of the entire table.
  • You want to apply Iceberg deletes (PositionDeletes and EqualityDeletes) for accurate query results.
  • Periodic full reloads fit your use case better than continuous streaming.

Create a refreshable table

Do not define column types in the CREATE TABLE statement. RisingWave automatically infers the schema from the Iceberg table. Only specify a PRIMARY KEY constraint if the corresponding column exists in the Iceberg table schema.

Parameters

RisingWave checks all refreshable tables at a configurable interval (default: 60 seconds, configured by stream_refresh_scheduler_interval_sec in the RisingWave configuration file). Setting a refresh_interval_sec value lower than this scheduler interval may result in refresh triggers not occurring at the expected frequency.
If you omit refresh_interval_sec, the table will only refresh when you manually execute REFRESH TABLE, giving you complete control over when data is loaded.

Manual refresh

You can manually trigger a refresh at any time using the REFRESH TABLE command:

Monitor delete files

You can verify discovered delete files via the rw_iceberg_files system catalog:
This query shows all data and delete files associated with the table. The content column indicates the file type:
  • Data: Regular data files
  • PositionDeletes: Position-based delete files
  • EqualityDeletes: Equality-based delete files

Monitor refresh status

Query the rw_catalog.rw_refresh_table_state system catalog to monitor refresh operations:
The current_status field shows the current state of the refresh job:
  • IDLE: No refresh operation is currently in progress
  • REFRESHING: A refresh operation is in progress
For more details, see REFRESH TABLE.

What’s next?

Query data

Once created, you can query data from the Iceberg source:

Query historical snapshots of your Iceberg data

Query historical snapshots of your Iceberg tables in batch queries. Fixed-snapshot time travel is not supported in materialized views, sinks, or other streaming jobs. For more information, see Time travel queries.

Continuous data processing jobs

You can create materialized views that continuously process data from the Iceberg source:

Inspect Iceberg metadata through system tables

Use system tables to inspect Iceberg metadata: