256 karma · joined June 26, 2010
shikhar@s2.dev
On cost, it's running the collector Node app (I'd expect a few $ per month at low volume), and the S2 stream backend.
If you use the S2 cloud service, cost is basically just the rrweb bytes. The rates are $0.075/GiB to write, $0.05/GiB-month to store, $0.10/GiB to read back over the internet. See s2.dev/pricing.md for an agent-friendly summary.
Assuming a typical few-minute session is ~1 MiB of events, ingesting it, storing it a month, and replaying it a couple of times (unlikely!):
1k sessions/mo ≈ $0.35
10k sessions/mo ≈ $3.50
100k sessions/mo ≈ $35
It's our favorite way of demoing s2.dev, https://x.com/jrdi/status/2014318511120670859
The durability is for being able to replay the stream, a hash will not let you reconstruct the original message(s).
If you just need ephemeral comms, making it persistent is indeed overkill. But reliability challenges often come up with seemingly ephemeral comms too – think streaming responses from an LLM. The last mile can be pretty flaky e.g. iOS will cancel connections when users background an app. Using a durable stream for persisting the tokens means a client can ask to resume from where it left off / from the beginning of the stream, and the data would be available without having to re-inference.
Did not architect explicitly for that, but should be viable. You could use the `Backend` directly, is what the REST handlers call https://docs.rs/s2-lite/latest/s2_lite/backend/struct.Backen...
Happy to accept contributions that make this more ergonomic.
> And am I understanding correctly that if I pointed 2 running instances of s2-lite at the same place in s3 there would be problems since slatedb is single writer?
SL8 will fence the older writer, thanks to S3 conditional writes. I think there would be potential for stale reads until the fencing happens...
ED: Fresh discussion in https://discord.com/channels/1232385660460204122/12323856609...
The stale read potential can be mitigated, https://github.com/s2-streamstore/s2/issues/91
gRPC ecosystem is also not very uniform despite its popularity, comes with bloat, is a bit of a mess in Python. I'm hoping QUIC enables a viable gRPC alternative to emerge.
Yes, this can be a good building block for broadcasting data streams.
s2-lite is single node, so to scale to that level, you'd need to add some CDN-ing on top.
s2.dev is the elastic cloud service, and it supports high fanout reads using Cachey (https://www.reddit.com/r/databasedevelopment/comments/1nh1go...)
ED: no k8s required for s2-lite, it is just a singe binary. It was an architectural note about our cloud service.
Will look into how to enable that option from s2-lite
And it has the durability of object storage rather than just local. SlateDB actually lets you also use local FS, will experiment with plumbing up the full range of options - right now it's just in-memory or S3-compatible bucket.
> So I'd try so share as much of the frontend code (e.g. the GRPC and REST handlers) as possible between these.
Right on, this is indeed the case. The OpenAPI spec is also now generated off the REST handlers from s2-lite. We are getting rid of gRPC, s2-lite only supports the REST API (+ gRPC-like session protocol over HTTP/2: https://s2.dev/docs/api/records/overview#s2s-spec)
https://s2.dev/blog/dst https://s2.dev/blog/linearizability
We have also adopted Antithesis for a more thorough DST environment, and plan to do more with it.
One day we will engage Kyle to Jepsen, too. I'm not sure when though.
Pros: unlimited streams with the durability of object storage – JetStream can only do a few K topics
Cons: no consumer groups yet, it's on the agenda
Plug: If you need granular, durable streams in a serverless context, check out s2.dev
It is also possible to stop requiring the header, but I think it would complicate the design around coalescing reads – the layer above foyer would have to track concurrent requests to the same object.
> foyer draws inspiration from Facebook/CacheLib, a highly-regarded hybrid cache library written in C++, and ben-manes/caffeine, a popular Java caching library, among other projects.
We built a S3 read-through cache service for s2.dev so that multiple clients could share a Foyer hybrid cache with key affinity, https://github.com/s2-streamstore/cachey
ED: Now I catch your drift, it would indeed be cool. ZeroFS requires a commitment to the SlateDB LSM data format.
Someone tried this with XTDB, https://github.com/chucklehead-dev/s2-log
Auto-scaled Kubernetes deployments, one for each availability zone, currently on m*gd instances which give us local NVMe. The pods are able to easily push GiBps with 1-2 CPUs used — network is the bottleneck so we made it a scaling dimension (thanks KEDA).
On the client side, each gateway process uses kube.rs to watch ready endpoints in the same zone as itself, and frequently polls /stats exposed by Cachey for recent network throughput as a load signal.
To improve hit rates with key affinity, clients use rendezvous hashing for picking a node, with bounded load (https://arxiv.org/abs/1608.01350) – if a node exceeds a predetermined throughput limit, the next choice for the key is picked.
We may move towards consistent hashing – it would be a great problem to have, if we needed so many Cachey pods in a zone that O(n) hashing was meaningful overhead! An advantage with the current approach is it does not suffer from the cascaded overflow problem (https://arxiv.org/abs/1908.08762).