<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[unofficial blog]]></title><description><![CDATA[unofficial blog]]></description><link>https://blog.schmizz.net</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1699415497815/R986WzqG_.png</url><title>unofficial blog</title><link>https://blog.schmizz.net</link></image><generator>RSS for Node</generator><lastBuildDate>Mon, 20 Apr 2026 15:46:31 GMT</lastBuildDate><atom:link href="https://blog.schmizz.net/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Designing serverless stream storage]]></title><description><![CDATA[I have alluded to "hypothetical S2" (Stream Store), a true counterpart to S3 for data in motion. As I work on making S2 real, I wanted to share the design and how it shaped up.
Vision
Unlimited streams
A pain point with most streaming data solutions ...]]></description><link>https://blog.schmizz.net/designing-serverless-stream-storage</link><guid isPermaLink="true">https://blog.schmizz.net/designing-serverless-stream-storage</guid><category><![CDATA[streaming]]></category><category><![CDATA[distributed system]]></category><category><![CDATA[Databases]]></category><category><![CDATA[System Architecture]]></category><dc:creator><![CDATA[Shikhar Bhushan]]></dc:creator><pubDate>Sun, 18 Feb 2024 15:42:46 GMT</pubDate><content:encoded><![CDATA[<p>I have alluded to "<a target="_blank" href="https://blog.schmizz.net/disaggregated-wal">hypothetical S2</a>" (<strong>S</strong>tream <strong>S</strong>tore), a true counterpart to S3 for data in motion. As I work on making <a target="_blank" href="https://s2.dev/">S2</a> real, I wanted to share the design and how it shaped up.</p>
<h3 id="heading-vision">Vision</h3>
<h4 id="heading-unlimited-streams">Unlimited streams</h4>
<p>A pain point with most streaming data solutions is how they limit the number of ordered streams ('partitions'), typically to a few thousand, and/or associate large fixed costs with each of them. This can lead to an impedance mismatch when it may be natural to model distinct streams for fine-grained entities, like users or listings.</p>
<p>Let's imagine building the ingest pipeline for a multi-tenant vector database. It would make sense to have a stream per index. You get some buzz and usage on your free tier blows up: suddenly you are scrambling to shard into multiple clusters. Maybe you start to question why you have to contend with clusters at all.</p>
<h4 id="heading-low-latency">Low latency</h4>
<p>IO to a local SSD is sub-millisecond, as is the typical latency in crossing availability zones. If a cloud database can offer single-digit millisecond response times, any slower for sequential data is a shame.</p>
<p>There are certainly use-cases where sub-second or even sub-10-second for "near-real-time" is good enough, but online systems should rightfully balk. There can be lots of services involved in a modern tech stack, and the foundational primitives need to minimize latency. Beyond obviously online usage where latency affects user experience, imagine emitting an audit event at the end of a Lambda function – waiting on an acknowledgment to retry failures can be a time slice you are paying compute for.</p>
<h4 id="heading-elastic-to-high-throughputs">Elastic to high throughputs</h4>
<p>Cloud VMs can easily offer many GiBps in and out (<a target="_blank" href="https://blog.enfabrica.net/the-next-step-in-high-performance-distributed-computing-systems-4f98f13064ac">networking is fast</a>), and not too far behind are local SSDs wielded well (<a target="_blank" href="https://itnext.io/modern-storage-is-plenty-fast-it-is-the-apis-that-are-bad-6a68319fbc1a">storage is fast</a>). You may experience dissonance checking out cloud streaming solutions that throttle ordered streams to a measly 1-10 MiBps.</p>
<p>When a busy database node can push hundreds of MiBps in a converged setup, <a target="_blank" href="https://blog.schmizz.net/disaggregated-wal">disaggregating its write-ahead log</a> is unworkable with such low throughput limits. Partitioning can be a viable strategy in other cases, but inconvenient and inefficient if you end up having to impose order later with stream processing.</p>
<h4 id="heading-truly-serverless">Truly serverless</h4>
<p>Serverless represents an ideal developer experience for an infrastructure product, elevating the level of abstraction to the workload rather than the physical resources powering it. S2 aspires to be <a target="_blank" href="https://erikbern.com/2021/04/19/software-infrastructure-2.0-a-wishlist.html">truly serverless</a>, with usage-based transparent pricing, and no faux-serverless <a target="_blank" href="https://www.gomomento.com/blog/fighting-off-fake-serverless-bandits-with-the-true-definition-of-serverless">bandit tricks</a>.</p>
<p>Some vendors seem to look at a serverless offering as a way to go "downmarket" or upsell dedicated resources beyond some scaling wall – and yet we have S3 <a target="_blank" href="https://press.aboutamazon.com/2006/3/amazon-web-services-launches">the OG</a> serving everyone from Netflix to tiny startups. Maybe S2 will offer dedicated single-tenant cells, but it should not be for lack of scalability or resource isolation in its default environment.</p>
<h4 id="heading-enable-the-next-generation-of-data-systems">Enable the next generation of data systems</h4>
<p>When data is moving reliably, there is a durable stream involved. Streams deserve to be a cloud storage primitive. To me this calls for intuitive, easy to integrate APIs over HTTP, like JSON and gRPC. The specifics will evolve, but S2 should always strive for simplicity.</p>
<p>Beyond core data operations like <code>append</code> / <code>pull</code> / <code>trim</code>, leases with fencing are a powerful abstraction for disaggregation. I certainly want it, in plotting a Kafka-on-S2 layer! I believe the best way to bring S2 to Kafka clients would be with an open-source wire-compatible layer that can be self-hosted, and is also made available as a serverless endpoint. The code can serve as an example of how to power distributed data systems with S2, with some of the neat features from the Kafka world like keyed compaction being natively integrated.</p>
<h3 id="heading-architecture">Architecture</h3>
<p>The S2 vision presents quite an engineering challenge, and the table stakes are high as well: highly available, durable, and secure.</p>
<p>I initially discounted object storage as a primary source of durability, because of the unacceptably high latency of hundreds of milliseconds for writes. The engineering investment and <a target="_blank" href="https://www.warpstream.com/blog/kafka-is-dead-long-live-kafka">bandwidth costs</a> involved in manually implementing replicated durability seemed necessary.</p>
<p>That changed with the <a target="_blank" href="https://aws.amazon.com/blogs/aws/new-amazon-s3-express-one-zone-high-performance-storage-class/">announcement of S3 Express</a> at the Nov 2023 AWS Re:invent, promising single-digit millisecond IOs albeit as a "One Zone" zonal service. I also learned about <a target="_blank" href="https://learn.microsoft.com/en-us/azure/storage/blobs/storage-blob-block-blob-premium">Azure <em>Premium</em> Blob Storage</a>, which is able to offer similarly low latencies regionally. Of the 3 major clouds, this leaves Google Cloud who certainly have SSD-based <a target="_blank" href="https://cloud.google.com/blog/products/storage-data-transfer/a-peek-behind-colossus-googles-file-system">Colossus</a> clusters internally, so I see it is a matter of time before they catch up with a "GCS Express". Suddenly, the future for <strong>fast</strong> cloud-provider-native object storage was looking bright.</p>
<p>With some performance testing, I determined that an IO size sweet spot for S3 Standard is 4 MiB, and the cost model for S3 Express already nudges one towards 512 KiB operations. As I reflected on previous experiments with local NVMe SSDs using Direct IO, a storage hierarchy was firming up. Direct IO forced me to issue 4K-multiple writes with great attention to driving concurrency, and larger sizes like 64 KiB helped with throughput. S3 was more forgiving on precise sizing of writes, but the higher latencies demanded amping up concurrency for a longer pipeline – you may recognize this as <a target="_blank" href="https://en.wikipedia.org/wiki/Little%27s_law">Little's law</a>.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td></td><td>Write size</td><td>Latency</td><td>Sticker price (1 GiB regional durability)</td></tr>
</thead>
<tbody>
<tr>
<td><em>Local SSD</em></td><td>64 KiB</td><td>sub-millisecond</td><td>$0.04 on bandwidth (albeit large discounts at scale!)</td></tr>
<tr>
<td><em>S3 Express</em></td><td>512 KiB</td><td>20 milliseconds</td><td>$0.01536 all-inclusive</td></tr>
<tr>
<td><em>S3 Standard</em></td><td>4 MiB</td><td>400 milliseconds</td><td>$0.00128 all-inclusive</td></tr>
</tbody>
</table>
</div><p>Operating across this full price-performance spectrum seemed within reach, with the right abstractions. Enabling disaggregated systems was one thing, S2 needed to internally disaggregate storage as well. By building a quorum protocol for a zonal service like S3 Express to achieve regional durability and availability, there was an exciting path to also leverage a similar mechanism for a purpose-built storage tier on local disks.</p>
<p>S2 calls this abstraction the chunk store, and it ended up with a surprisingly small interface. Chunks can be comprised of records from many streams – multiplexing helps achieve the optimal write size. An easily verifiable protocol performs quorum writes for durability, and cheaply minimizes the "window of uncertainty" chunk range which will require quorum reads in case of recovery. It would be accurate to characterize the sequence of chunks as a replicated write-ahead log.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1708119035895/4df7874b-c94b-4614-aa08-32b27c2c392b.png" alt class="image--center mx-auto" /></p>
<p>A channel is diskless, serving real-time reads (i.e. the last N seconds of records) from memory, and works against a specific chunk store type. Of course, memory is a limited resource that a high throughput channel would quickly churn through – which is why channels are continuously, asynchronously offloading per-stream data segments to object storage, and garbage collecting chunks. Higher time-to-first-byte for a lagging reader is not a concern, and comes with a nice win on scalability of read throughput.</p>
<p>Elasticity arises from streams being represented as a chain of lightweight "streamlets", with stream metadata storage centralized. This aspect of the design is inspired by <a target="_blank" href="https://www.usenix.org/conference/osdi20/presentation/balakrishnan">Delos</a>, which calls log epochs "loglets" and innovated with the idea of virtualizing consensus. The control plane can use a simple protocol for live-migrating streams between channels in response to changing workloads – and even reconfigure streams to different types of chunk storage!</p>
<p>To unlock an unlimited number of streams, metadata storage needs to be extremely scalable. It stands behind a minimal interface which can be implemented efficiently against fast cloud-provider-native databases like AWS DynamoDB, GCP Spanner, and Azure CosmosDB, which tend to have even higher availability SLAs than object storage. Metadata reads are largely cacheable, with care to ensure safety in case of stale reads.</p>
<p>This kind of decoupled, multi-tenant architecture is key to delivering on a serverless experience. The calculus on physically separating components is very different from a piece of software intended for users to run, where single-binary-minimal-dependencies tends to provide the best experience.</p>
<p>It was fun to hack on a prototype for S2 that can work against both S3 Standard and S3 Express "Three Zone" as chunk stores, with the performance and cost profile I was shooting for. The latency with S3X3Z is <a target="_blank" href="https://github.com/awslabs/aws-sdk-rust/issues/992#issuecomment-1870538735">not quite</a> single-digit milliseconds, but close enough that it makes sense to push back a native chunk store.</p>
<p>I glossed over many interesting details, and a lot is currently up in the air. I look forward to sharing more as the work continues!</p>
<p>Now begins the journey of building a great team and delivering on the vision for S2 with a preview launch targeted for later this year. If you are intrigued and want to be an early user or perhaps even collaborate as a design partner, please signup on the <a target="_blank" href="https://docs.google.com/forms/d/e/1FAIpQLSd8zyYhYEyS9q25h7okSwtfAkq2DB3p8a5gBNLajFpuh2bTYA/viewform?usp=sf_link">waitlist</a>.</p>
]]></content:encoded></item><item><title><![CDATA[The disaggregated write-ahead log]]></title><description><![CDATA[The traditional way replicated systems are architected is to physically co-locate the write-ahead log (WAL) on the nodes where the state is being maintained. Then a consensus protocol like Paxos or Raft is used to make sure the log on each replica ag...]]></description><link>https://blog.schmizz.net/disaggregated-wal</link><guid isPermaLink="true">https://blog.schmizz.net/disaggregated-wal</guid><category><![CDATA[distributed system]]></category><category><![CDATA[Databases]]></category><category><![CDATA[Distributed Database]]></category><category><![CDATA[streaming]]></category><category><![CDATA[System Design]]></category><dc:creator><![CDATA[Shikhar Bhushan]]></dc:creator><pubDate>Wed, 08 Nov 2023 16:44:40 GMT</pubDate><content:encoded><![CDATA[<p>The traditional way replicated systems are architected is to physically co-locate the <a target="_blank" href="https://en.wikipedia.org/wiki/Write-ahead_logging">write-ahead log</a> (WAL) on the nodes where the state is being maintained. Then a consensus protocol like Paxos or Raft is used to make sure the log on each replica agrees. With many classical databases that have been around a while, instead of consensus there may be a configuration-driven primary/backup scheme.</p>
<p>This converged approach is not <em>that</em> different logically even with the physical decoupling of compute and storage as pioneered by hyperscalers. At Google, locally attached disks are rarely relied upon – you must use Colossus, the current generation of the <a target="_blank" href="https://research.google/pubs/pub51/">Google File System</a> and "<a target="_blank" href="https://cloud.google.com/blog/products/storage-data-transfer/a-peek-behind-colossus-googles-file-system">the secret scaling superpower behind Google's storage infrastructure</a>". All the data systems used internally at Google and those made available as cloud services like Bigtable and Spanner store logs <em>and</em> state in Colossus.</p>
<p>Colossus is a <strong>zonal service</strong>, so these systems still need to implement replication protocols to make them resilient to a single zone or region's unavailability. This is apparent if you have dealt with <a target="_blank" href="https://cloud.google.com/bigtable/docs/replication-settings">Bigtable replication</a>, which is async between zonal clusters. Other services like <a target="_blank" href="https://cloud.google.com/spanner/docs/instance-configurations">Spanner</a> offer a higher-level perspective of a regional or multi-regional deployment.</p>
<p>AWS went in a rather different direction. This <a target="_blank" href="https://www.youtube.com/watch?v=QVvFVwyElLY&amp;t=2650s">2014 re:Invent talk</a> describes their evolution with distributed systems that had led them to embrace a <em>transactional journal</em> primitive. It is a <strong>multi-zone replicated service</strong>, and now "powers some of the biggest AWS databases and retail services such as DynamoDB, Amazon S3, Amazon QLDB, Amazon SWS, Amazon SNS, and many others" (<a target="_blank" href="https://www.linkedin.com/pulse/day-life-thomas-price/">source</a>).</p>
<p>As a building block, this represents incredible leverage for AWS. <a target="_blank" href="https://aws.amazon.com/memorydb/">MemoryDB</a> which debuted in 2021 stands out to me. You get a highly durable Redis usable as a primary data store, for a pretty small write latency tradeoff of single-digit milliseconds. Meanwhile, Redis Labs has a <a target="_blank" href="https://github.com/RedisLabs/redisraft">Raft module</a> which is still experimental. How did AWS do it? See for yourself:</p>
<p><a target="_blank" href="https://aws.amazon.com/memorydb/"><img src="https://d1.awsstatic.com/product-page-diagram_Amazon-MemoryDB-for-Redis.38339d976bd9b151350f496469d4d54b21173523.png" alt="AWS MemoryDB WAL data flow" /></a></p>
<p>Outside of AWS, Meta engineers in their blog on <a target="_blank" href="https://engineering.fb.com/2023/05/16/data-infrastructure/mysql-raft-meta/">using Raft for MySQL replication</a> speculate a follow-up: "Another idea that we are considering is to disentangle the log from the state machine (the database) into a disaggregated log setup. This will allow the team to manage the concerns of the log and replication separately from the concerns of the database storage and SQL execution engine."</p>
<p>At sub-hyper-scale too, we can find examples of systems successfully leveraging disaggregated WALs:</p>
<ul>
<li><p><a target="_blank" href="https://go.fauna.com/guide/architectural-overview">Fauna</a>, the serverless document-relational hybrid database, runs a <a target="_blank" href="https://blog.acolyer.org/2019/03/29/calvin-fast-distributed-transactions-for-partitioned-database-systems/">Calvin-inspired</a> transaction protocol on top of a partitioned replicated log, delivering strict serializability with multi-region replication.</p>
</li>
<li><p><a target="_blank" href="https://pulsar.apache.org/docs/3.1.x/concepts-architecture-overview/">Pulsar</a> and <a target="_blank" href="https://cncf.pravega.io/docs/latest/pravega-concepts/#architecture">Pravega</a> are streaming data solutions relying on <a target="_blank" href="https://bookkeeper.apache.org/">BookKeeper</a> for record storage, together with <a target="_blank" href="https://zookeeper.apache.org/">ZooKeeper</a> to coordinate since BK eschews ordering.</p>
</li>
<li><p><a target="_blank" href="https://neon.tech/docs/introduction/architecture-overview">Neon</a>, the serverless Postgres system inspired by AWS Aurora (of <a target="_blank" href="https://www.amazon.science/publications/amazon-aurora-design-considerations-for-high-throughput-cloud-native-relational-databases">"the log is the database"</a>), built a multi-tenant WAL service called Safekeeper and have shared insights on their <a target="_blank" href="https://neon.tech/blog/paxos">choice of Paxos</a> for it.</p>
</li>
</ul>
<p><a target="_blank" href="https://neon.tech/blog/paxos"><img src="https://neon.tech/_next/image?url=https%3A%2F%2Fneon-hwp.dreamhosters.com%2Fwp-content%2Fuploads%2F2022%2F08%2Fdiagram-3.jpeg&amp;w=3840&amp;q=85" alt="Neon's WAL data flow" /></a></p>
<p>Even though pretty much every distributed data system stands to benefit from replicated logs being a commodity, the only commodity in that diagram today is object storage. The scope of <a target="_blank" href="https://wesmckinney.com/blog/looking-back-15-years/#conclusions-and-looking-ahead">composable data systems</a> needs to extend to replicated logs on this journey of the "Great Decoupling", lest it turn into the "Great Divide" between the building blocks available to hyperscalers vs outsiders.</p>
<p>S3 revolutionized how slow immutable data is stored and accessed, where is the counterpart for fast data streams? S3 has been called the <a target="_blank" href="https://www.youtube.com/watch?v=vLlSoHqTTN8&amp;t=149s">gold standard for serverless</a>, and has even been proposed as the <a target="_blank" href="https://medium.com/innovationendeavors/s3-as-the-universal-infrastructure-backend-a104a8cc6991">universal infrastructure backend</a>. I agree on the former, and on the latter I would argue that object stores are not comprehensive enough, as they do not solve for cheap small writes, low latency IO, or coordination requirements.</p>
<p>I believe that if distributed systems hackers had the equivalent of S3 for logs – truly serverless API, single-digit-milliseconds to tail and append, for a practically unlimited number of them with bottomless storage and elastic throughput – we would unlock a ton of design innovation.</p>
<p>Maybe it can even be called S2, the Stream Store. Hypothetical S2 can take care of replicating within and between regions and even across clouds, so long as you pay the speed of light tax. Hypothetical S2 does a bit more to simplify the layers above – it makes <a target="_blank" href="https://maheshba.bitbucket.io/blog/2023/05/06/Leadership.html">leadership above the log</a> convenient with leases and fenced writes.</p>
<p>Building a durable execution engine? There's your fast side effect journal.</p>
<p>Distributed transactions? Use a coordinator log for <a target="_blank" href="https://en.wikipedia.org/wiki/Two-phase_commit_protocol">2PC</a>.</p>
<p>Need to quickly acknowledge writes while preparing index chunks persisted in S3? S2 can be your trimmable, durable buffer.</p>
<p>Unifying streaming and queuing, disklessly? Pulsar charted the path, let's take it to the next level without the JVM clusters.</p>
<p>Ingestion pipeline for a multi-tenant data store? Granular streams seem perfect, model a log per tenant-use-case.</p>
<p>Event sourcing? S2 for the log and S3 for state snapshots.</p>
<p>What would S2 enable for you? It's okay to dream!</p>
<hr />
<p><em>Update: I am working on making</em> <a target="_blank" href="https://s2.dev/"><em>S2</em></a> <em>real!</em></p>
<p><em>Proprietary systems are described based on public info, let me know if I got something wrong and I'd be happy to fix it!</em></p>
]]></content:encoded></item></channel></rss>