Durable Streams API https://s2.dev
  • Rust 99.3%
  • Shell 0.3%
  • Smarty 0.2%
  • Just 0.1%
Find a file
release-pleaze[bot] 1fa28e4a09
chore: release (#429)
## 🤖 New release

* `s2-common`: 0.33.1 -> 0.34.0 (⚠ API breaking changes)
* `s2-api`: 0.28.4 -> 0.28.5 (✓ API compatible changes)
* `s2-lite`: 0.30.5 -> 0.30.6
* `s2-sdk`: 0.27.1 -> 0.28.0 (⚠ API breaking changes)
* `s2-cli`: 0.30.5 -> 0.30.6

### ⚠ `s2-common` breaking changes

```text
--- failure enum_variant_added: enum variant added on exhaustive enum ---

Description:
A publicly-visible enum without #[non_exhaustive] has a new variant.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#enum-variant-new
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.46.0/src/lints/enum_variant_added.ron

Failed in:
  variant BasinScope:AwsUsWest2 in /tmp/.tmpYcrI2D/s2/common/src/types/basin.rs:210
  variant BasinScope:AwsEuNorth1 in /tmp/.tmpYcrI2D/s2/common/src/types/basin.rs:212
```

### ⚠ `s2-sdk` breaking changes

```text
--- failure enum_variant_added: enum variant added on exhaustive enum ---

Description:
A publicly-visible enum without #[non_exhaustive] has a new variant.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#enum-variant-new
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.46.0/src/lints/enum_variant_added.ron

Failed in:
  variant BasinScope:AwsUsWest2 in /tmp/.tmpYcrI2D/s2/sdk/src/types.rs:863
  variant BasinScope:AwsEuNorth1 in /tmp/.tmpYcrI2D/s2/sdk/src/types.rs:865
```

<details><summary><i><b>Changelog</b></i></summary><p>

## `s2-common`

<blockquote>

## [0.34.0] - 2026-05-04

### Features

- Add aws:us-west-2 and aws:eu-north-1 basin scopes
([#430](https://github.com/s2-streamstore/s2/issues/430))

<!-- generated by git-cliff -->
</blockquote>

## `s2-api`

<blockquote>

## [0.28.5] - 2026-05-04

### Features

- Add aws:us-west-2 and aws:eu-north-1 basin scopes
([#430](https://github.com/s2-streamstore/s2/issues/430))

### Miscellaneous Tasks

- Sync specs submodule
([#427](https://github.com/s2-streamstore/s2/issues/427))

<!-- generated by git-cliff -->
</blockquote>

## `s2-lite`

<blockquote>

## [0.30.6] - 2026-05-04

<!-- generated by git-cliff -->
</blockquote>

## `s2-sdk`

<blockquote>

## [0.28.0] - 2026-05-04

### Features

- Add aws:us-west-2 and aws:eu-north-1 basin scopes
([#430](https://github.com/s2-streamstore/s2/issues/430))

<!-- generated by git-cliff -->
</blockquote>

## `s2-cli`

<blockquote>

## [0.30.6] - 2026-05-04

### Features

- Add aws:us-west-2 and aws:eu-north-1 basin scopes
([#430](https://github.com/s2-streamstore/s2/issues/430))

<!-- generated by git-cliff -->
</blockquote>


</p></details>

---
This PR was generated with
[release-plz](https://github.com/release-plz/release-plz/).

Co-authored-by: release-pleaze[bot] <262023388+release-pleaze[bot]@users.noreply.github.com>
History 2026-05-04 17:41:21 +03:00
.claude/skills/release ci: update discrepancies in release skill (#176) 2026-02-05 13:22:46 -07:00
.github/workflows chore(api): include v1 s2.proto file in the package (#423) 2026-04-24 12:44:16 -06:00
api chore: release (#429) 2026-05-04 17:41:21 +03:00
assets readme tweaks (#90) 2026-01-21 11:19:35 -05:00
charts/s2-lite-helm Bump s2-lite-helm chart to appVersion 0.30.5 2026-04-27 21:05:30 +00:00
cli chore: release (#429) 2026-05-04 17:41:21 +03:00
common chore: release (#429) 2026-05-04 17:41:21 +03:00
docs/adr docs: encryption key header (#416) 2026-04-21 21:36:32 -04:00
hooks fix: reject . and .. as access token and stream names (#318) 2026-03-15 11:27:54 +05:30
lite chore: release (#429) 2026-05-04 17:41:21 +03:00
sdk chore: release (#429) 2026-05-04 17:41:21 +03:00
.gitignore fix(lite): allow http endpoints for S3-compatible object stores (#303) 2026-03-06 10:37:59 -05:00
.gitmodules chore: fix submodule sync workflow (#57) 2026-01-14 23:47:18 -05:00
.rustfmt.toml init 2025-11-07 12:09:00 -08:00
AGENTS.md feat(lite): add local filesystem support; startup sleep for safe fencing (#94) 2026-01-26 11:26:56 -05:00
Cargo.lock chore: release (#429) 2026-05-04 17:41:21 +03:00
Cargo.toml chore: release (#429) 2026-05-04 17:41:21 +03:00
CLAUDE.md s2-lite backend (#11) 2026-01-04 23:37:38 -05:00
cliff.toml chore: rejig versioning and release workflow (#163) 2026-02-05 00:45:44 -07:00
deny.toml test(lite): simplify backend integration tests and tighten read coverage (#374) 2026-04-11 18:35:07 -04:00
Dockerfile ci: fix missing sdk mount in Dockerfile (#224) 2026-02-16 18:20:02 -07:00
install.sh chore: fix CLI installer (#244) 2026-02-24 15:43:45 -07:00
justfile test: isolate CLI config tests and exclude live SDK tests (#366) 2026-04-06 12:47:29 -04:00
LICENSE update copyright line in license 2026-01-17 17:03:56 -05:00
README.md docs: update compatibility section in README (#386) 2026-04-13 19:35:23 -06:00
release-plz.toml chore: rejig versioning and release workflow (#163) 2026-02-05 00:45:44 -07:00

S2, the durable streams API

s2.dev is a serverless datastore for real-time, streaming data.

This repository contains:

  • s2-cli - The official S2 command-line interface
  • s2-lite - An open source, self-hostable server implementation of the S2 API
  • s2-sdk - The official Rust SDK for S2

Installation

Homebrew (macOS/Linux)

brew install s2-streamstore/s2/s2

Cargo

cargo install --locked s2-cli

Release Binaries (macOS/Linux)

curl -fsSL https://raw.githubusercontent.com/s2-streamstore/s2/main/install.sh | bash

Or specify a version with VERSION=x.y.z before the command. See all releases.

Docker

docker pull ghcr.io/s2-streamstore/s2

s2-lite

s2-lite is embedded as the s2 lite subcommand of the CLI. It's a self-hostable server implementation of the S2 API.

It uses SlateDB as its storage engine, which relies entirely on object storage for durability.

It is easy to run s2 lite against object stores like AWS S3 and Tigris. It is a single-node binary with no other external dependencies.

You can also simply not specify a --bucket, which makes it operate entirely in-memory (or use --local-root to persist to local disk instead).

Tip

When you point lite at a --bucket, data is always durable on object storage before being acknowledged or returned to readers — just like s2.dev.

The optional in-memory mode (no --bucket or --local-root specified) just makes it an effective S2 emulator for integration tests.

Quickstart

Here's how you can run in-memory without any external dependency:

# Using Docker
docker run -p 8080:80 ghcr.io/s2-streamstore/s2 lite

# Or directly with the CLI
s2 lite --port 8080
AWS S3 bucket example
docker run -p 8080:80 \
  -e AWS_PROFILE=${AWS_PROFILE} \
  -v ~/.aws:/home/nonroot/.aws:ro \
  ghcr.io/s2-streamstore/s2 lite \
  --bucket ${S3_BUCKET} \
  --path s2lite
Static credentials example (Tigris, R2 etc)
docker run -p 8080:80 \
  -e AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} \
  -e AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} \
  -e AWS_ENDPOINT_URL_S3=${AWS_ENDPOINT_URL_S3} \
  ghcr.io/s2-streamstore/s2 lite \
  --bucket ${S3_BUCKET} \
  --path s2lite

Note

Point the S2 CLI or SDKs at your lite instance like this:

export S2_ACCOUNT_ENDPOINT="http://localhost:8080"
export S2_BASIN_ENDPOINT="http://localhost:8080"
export S2_ACCESS_TOKEN="ignored"

Let's make sure the server is ready:

while ! curl -sf ${S2_ACCOUNT_ENDPOINT}/health -o /dev/null; do echo Waiting...; sleep 2; done && echo Up!

Install the CLI (see Installation above) or upgrade if s2 --version is older than 0.26

Let's create a basin with auto-creation of streams enabled:

s2 create-basin liteness --create-stream-on-append --create-stream-on-read

Test your performance:

s2 bench liteness --target-mibps 10 --duration 5s --catchup-delay 0s

S2 Benchmark

Now let's try streaming sessions. In one or more new terminals (make sure you re-export the env vars noted above),

s2 read s2://liteness/starwars 2> /dev/null

Now back from your original terminal, let's write to the stream:

nc starwars.s2.dev 23 | s2 append s2://liteness/starwars

S2 Star Wars Streaming

Kubernetes Deployment

Deploy s2-lite to Kubernetes using Helm. See the Helm chart documentation for installation instructions and configuration options.

Monitoring

/health will return 200 on success for readiness and liveness checks

/metrics returns Prometheus text format

Internals

SlateDB settings

Settings reference

Use SL8_ prefixed environment variables, e.g.:

# Defaults to 50ms for remote bucket / 5ms in-memory
SL8_FLUSH_INTERVAL=10ms

Design

Concepts

  • HTTP serving is implemented using axum
  • Each stream corresponds to a Tokio task called streamer that owns the current tail position, serializes appends, and broadcasts acknowledged records to followers
  • Appends are pipelined to improve performance against high-latency object storage
  • lite::backend::kv::Key documents the data modeling in SlateDB

Compatibility

API Coverage

Complete specs are available:

  • OpenAPI for the REST-ful core
  • Protobuf definitions
  • S2S, which is the streaming session protocol

Important

Unlike the cloud service where the basin is implicit as a subdomain, /streams/* requests must specify the basin using the S2-Basin header. The SDKs take care of this automatically.

Endpoint Support
/basins Supported
/streams Supported
/streams/{stream}/records Supported
/access-tokens Not supported https://github.com/s2-streamstore/s2/issues/28
/metrics Not supported