# XREAD and Blocking Reads — Redis Pub/Sub & Streams

Source: https://www.skillbyai.com/en/redis-streams/s-read

> Tail a stream with XREAD, blocking and the special $ ID.

## Following a stream like tail -f

`XRANGE` reads history; **`XREAD`** is designed for **following** one or more streams. You pass, for each stream, the **last ID you have seen**, and Redis returns entries with greater IDs. With **`BLOCK milliseconds`**, the call waits for new entries if none are available, like `tail -f`; `BLOCK 0` waits forever. The special ID **`$`** means "only entries added after this call", useful for the very first read when you do not care about history. After each batch, remember the **last ID returned** and pass it in the next call, so you never miss or repeat entries. `COUNT` limits the batch size. `XREAD` is for **independent readers**: every reader sees every entry and tracks its own position. When several workers must **share** the work, each entry going to only one of them, use consumer groups instead (next section).

## A simple stream follower

The reader keeps its own last ID so it resumes correctly after each batch.

```python
last_id = "$"            # start with new entries only (use "0" to read from the beginning)

while True:
    batches = r.xread({"orders": last_id}, count=100, block=5000)   # wait up to 5 s
    for stream_name, entries in batches:
        for entry_id, fields in entries:
            print(entry_id, fields["orderId"], fields["status"])
            last_id = entry_id      # remember position
    # persist last_id somewhere if the reader must resume after a restart
```

## Bookmarking a newspaper archive

XREAD is reading the archive from your bookmark onwards. Each reader has their own bookmark, and reading does not tear pages out, so others can read the same pages.

**Quiz:** What does the special ID `$` mean in `XREAD ... STREAMS orders $`?

- [ ] Read from the very first entry
- [x] Return only entries added after the call starts
- [ ] Read the last entry again
- [ ] Delete the stream

*Answer:* Return only entries added after the call starts. `$` means the current last ID, so only newer entries are returned.
