Post

Hi protocol friends! I've been cooking up a Very Large PDS (vlpds) implementation capable of scaling up to billions of accounts and down to just one. It uses Object Storage as its only state, supports HA operation, live scaling up and down, is feature-complete with the reference PDS, and is FOSS.

vlpds.jazco.devOverview · vlpds docsAn atproto PDS whose only durable storage is an object store. Any node serves any request, one node can run a personal server for free, and a few nodes can carry all of Bluesky's write load.

I've tested vlPDS on an instance as small as a 2vCPU 4GB RAM, 40GB NVME OVH VPS at which scale it could host 10,000 of the most active accounts on the network comfortably with overhead. Operating costs at that scale are $4.50/mo for the instance and ~$75 on R2 for ops plus storage.

At Bluesky production scale, hosting the entire network with room for 3x peak commit spikes during the day, vlPDS can be hosted on 3 x 6vCPU machines with 32GB RAM and 400GB local NVME. Adding in the Object Storage costs and it comes to roughly $1.5k/mo (plus blob storage costs).

0 reposts73 likes

Oh yeah and that setup can support 10x the scale of today's production load comfortable (including the 3x traffic spike overhead)!!

Another fun fact, a single node can handle 300k+ proxied requests per second to various AppViews with realistic payload/response sizes and latencies!

The primary focus here is on reliability, scalability, and ease of operation. Things should be very set-it-and-forget and ideally in the worst case scenario of losing an entire node you'd have at most a 12 second blip of some of your shards write availability. It also supports manual shard splitting

vlPDS uses a per-node in-bucket WAL complementing the per-shard SlateDB to better amortize Class-A operations against your bucket without sacrificing durability. Writes get a 200 only once they're durable in the WAL in object storage and flush from SlateDB's memtables within 10 seconds.

On a crash recovery, the new owning node claims the shard, replays the relevant data from the crashed node's WAL, and catches up the SlateDB state before accepting writes to repos assigned to that shard again, all within 12 seconds.

seems like a very vertical workload, given the state is an external object storage what stops you from serving it horizontally in an auto-scaling environment instead? wouldn't it be more effective?

it is horizontally scalable, but each node increases the baseline load on object store operations so cost-wise it generally scales better vertically.