Skip to main content
A table-valued function (TVF) that reads from a stream: messages from a Kafka topic, or change events from a Postgres table or MongoDB collection. READ_STREAM returns a table with the stream’s declared columns plus source-specific metadata pseudo-columns. A stream tracks a consumed position (Kafka offsets, a Postgres replication-slot position, or a MongoDB resume token). When consume is true, the position advances with the transaction that reads, so each read returns only new data. Position updates commit atomically with the data they produced, which makes ingestion through READ_STREAM exactly-once. To load the current contents of a Postgres table or MongoDB collection rather than its changes, use READ_SNAPSHOT. For continuous ingestion of Postgres or MongoDB change feeds, prefer a CDC table, which runs this machinery for you; direct READ_STREAM over CDC streams is most useful for inspection and custom pipelines.

Syntax

Parameters

Setting consume to true makes the query a write operation. Read-only queries, such as standalone SELECT statements outside of CREATE TABLE AS SELECT or INSERT INTO ... SELECT, cannot consume from a stream. Either set consume => false or use READ_STREAM inside a write statement.

Return type

The result has the stream’s declared columns plus pseudo-columns that depend on the source. Pseudo-columns are not included in SELECT *; reference them explicitly, double-quoted (for example SELECT "$op", * FROM ...).

Kafka streams

How raw messages map to columns is set by the stream’s TYPE (JSON, CSV, RAW_TEXT, BINARY); see Kafka stream types.

Postgres streams

Private Preview FeatureThis feature is currently in private preview. Contact support@firebolt.io to request early access.
Rows arrive in commit order; uncommitted transactions are never surfaced. One read returns as many whole source transactions as the source has ready, up to limit_rows, so a busy source is caught up in one statement rather than one statement per transaction. The result is delivered as several row batches; row order within a batch is source order, and batches themselves can arrive out of order, because a read decodes them in parallel by default. Order by $stream_row_number where delivery order matters. See Postgres CDC for delete and key-update row shapes. Exactly-once holds when the statement consumes everything the read delivers. Do not put a LIMIT above a consuming read: a LIMIT that is satisfied before the read has drained ends it early. The rows already delivered are committed, but the stream’s position is not advanced: nothing is lost, and the next read delivers those rows again, so such a statement is at-least-once. Use limit_rows to bound a read instead; it stops at transaction boundaries and moves the position.

MongoDB streams

Private Preview FeatureThis feature is currently in private preview. Contact support@firebolt.io to request early access.
Besides the pseudo-columns, a MongoDB stream always has the columns _id and doc; see CREATE STREAM. A first consuming read starts at the position CREATE STREAM recorded; it does not replay older history. A read returns changes in the order the source committed them, until timeout_millis has passed or it has limit_rows rows, and then stops at the next transaction boundary. A multi-document transaction is never split across reads. A read can run up to 500 ms past timeout_millis while it waits for new changes. A consuming read that returns no rows still moves the stored position forward, which keeps an idle stream’s position inside the oplog. A drop, rename or invalidation of the collection ends its change stream: the read returns the changes before it, and the next read fails. A statement reads a MongoDB stream at most once, counting READ_STREAM and READ_SNAPSHOT together and a WITH query once per reference, because each read stores the stream’s whole position. A view cannot read a MongoDB stream.

Examples

Peek at a stream without consuming

Inspect change events on a CDC stream

Ingest Kafka messages into a managed table

The stream’s offsets advance with the insert, so running the statement again returns only messages that arrived after the previous read.

Filter and transform while reading

Use Kafka pseudo-columns

Managing consumed positions

Kafka offsets are visible in information_schema.streams and can be repositioned with ALTER STREAM ... SET PARTITION ... OFFSET .... Postgres streams track their position in the source’s replication slot; MongoDB streams store a resume token. Neither is manually repositionable; see the Postgres CDC and MongoDB CDC operations sections.