Zicklag's Leaflets

How to Make a PDS - Part 1

So you want to make a PDS? Or maybe you want to watch some poor fool try? In this series I might make a PDS, or not.

March 07, 2026

Zicklag's avatar
Zicklag
5d

There should be a "How to Make a PDS" tutorial. The more people there are that can make PDSes, the more impossible to stop ATProto will be.

Zicklag's avatar
Zicklag
5d

And maybe I will stop feeling like ATProto is a little too much to ask for just to have a "universal" login provider.

This won't be exactly what I imagined, but it'll be something.

Note: It's actually quite possible I never finish this. So while it will be someting it may not be anything more than what you find below. We'll see.

Recently I ran into someone who made a personal, experimental PDS implementation.

I have moved my to own PDS @sgo.to!'s avatar
I have moved my to own PDS @sgo.to!
1w

It was vibe coded in 2 days

That seems like a pretty good sign as far as how possible it is to make one.

On top of my general interest in the idea, at we recently realized that we might end up essentially making our own PDS with extra features for communities, privacy & realtime messaging. We're finding we agree with more of ATProto's design decisions than we thought we might.

Anyway to learn the ropes I'm going to try to make a PDS using Rivet, and awesome, distributed actor framework. In the interest of the blog series, I figured I'd journal about it as I tried it out, too.

Now the goal here isn't to make a PDS from scratch. I don't want to implement an MST or anything else really that I don't have to. So we're going to try and re-use ATProto's reference implementations of everything we can, while maintaining full controll over the networking, storage, and overall design of the PDS ourselves.

I've never done this before, so again this is not so much a tutorial as a journal, but it might be interesting. Let's get started!

Step 1 - Read the Docs

First let's head to the ATProto docs site, atproto.com. In particular the overview of the specs section looks like a good place to start.

  • Overview: I'm pretty familiar with most of ATProto, and after reading the overview, there wasn't anything new to me, so I moved on.

  • Data Model: Some good info I mostly already knew. Might need to come back to some details during implementation, but libraries will be handling most of this I think.

  • Lexicon: Barely skimmed this 'cause I've read it before.

  • Cryptography: Skimmed it. Will use libraries mostly for this.

  • Accounts: Read through this. It had some good info on accounts and their statuses and how the network is expected to respond to active or inactive accounts.

  • Repository: Pretty meaty section worth reading through. I skimmed some of the MST implementation details, but got a good overview of how the repository is implemented.

  • Media Blobs: Easy to read-through. Has good considerations about security and blob handling.

  • Labels: These are interesting, but I only skimmed the page for now. I don't think I need to worry about labels just yet.

  • XRPC: Good to know most of the stuff in here.

  • Oauth: The infamous OAuth. I read most of this, but skimmed over some of the details. I'm going to try and get a library to do this for me if at all possible.

  • Permissions: Skipping for now, I've mostly read it before.

  • Event Stream: Skipped through most of this, but got the general idea.

  • Sync: Very interesting. I found it cool that you can efficiently sync and verify ATProto repos. That could be really good for live, incremental backups of your PDS.

  • I'm pretty familiar with these so I just skipped this for now: DID, Handle, NSID, TSID, Record Key, at://.

And there! I've sort of read the ATProto spec! Honestly it's not that bad. Most of it reads easy enough. I can wait to get into the details on some of it until later. It's kind of a mild, pleasant surprise. I didn't think it would be that bad, but I was suprised how lean the protocol actually is.

Now I've got to figure out what to work on first.

Interlude - More on Rivet

I just wanted to drop a quick note about Rivet here and why I'm trying it out. In we're realizing that the very event-driven nature of it fits very well into an actor model.

As we've looked into doing more integrations with other ATProto apps, the ability to make new integrations and server-powered functionality on top of Roomy quickly has shown it's importance.

Rivet seems like a very powerful framework for making applications using an actor model, and it looks like it'll be fun to try out, so I'm playing with it for this week-end project.

Rivet looks really cool to me, but I want to try it out to see if it's as cool as I think it is. I hear a lot of developers who love how easy cloudflare makes things, and yet feel afraid of Cloudflare as being the internet's off-switch if everybody uses it. Rivet is also interesting because it seems like an Open Source alternative to Cloudflare workers.

Random side note, I've also found the Railway cloud since it was mentioned in the Rivet deployment options, and I'm really liking it so far.

What Next?

OK, so I've read the docs, and I need to pick what to work on first.

I think OAuth is probably one of the worste things to have to get working. Since it's one of the first steps for using the PDS for anything, I think I'll start on that. Hopefully I can re-use an existing authorization server library or something.

That's for the next post!

Subscribe to Zicklag's Leaflets
to get updates in Reader, RSS, or via Bluesky Feed
How to Make a PDS - Part 2

pds
atproto
rivet
actor model
how to