Michał Sapka's website

Mastodon and ActivityPub

After lengthy deliberations, I joined Mastodon. This website still has an auto-posting account on Twitter1, but I don’t read anything there. Mastodon, on the other hand, is an open-source set of communities without Elon. May be interesting

I was not sure which instance I wanted to join, but in the end, the list was limited to: https://bsd.network/ https://emacs.ch

The question was, am I more of an Emacs type of person or more of a BSD one? Well, I spend hours in Emacs daily, and I tinkered with it much more, so without further delay, you can find me under


However, I am still against social media, as it warps the mind and steals time. I don’t want Mastodon to take too much of my time and mind, so I have decided:

For now, you can find me there, and I will respond to messages. We will see what the future brings.

This is also an excellent opportunity to learn about the underlying technology.

What is a Mastodon?

Mastodon is a decentralized social media platform. Instead of a central server (think twitter.com), anyone can spin up their Mastodon instance. You can easily create one for bread bakers, Emacs users, or your neighborhood.

What is cool and what makes Mastodon interesting is the fact that a user exists on a given instance (like me on emacs.ch), but he can follow and communicate with any other user having an account on any other server (like Ruben on bsd.network3)

This intercommunication is called federation. In fact, Mastodon can communicate not only with other instances of Mastodon but any other service implementing ActivityPub standard4. Such services are sometimes referred to as fediverse5/

Yeah, open standards!

Though it’s worth mentioning that in its current form, Fediverse is dominated by Mastodon.

Activity Pub

ActivityPub is a protocol for decentralized social networks based on ActivityStreams vocabulary and syntax6 supported by W3C organization.

The standard defines two layers:

  1. A server-to-server protocol. This is what makes the federation work, as it allows instances to exchange data.
  2. A client-to-server protocol. This, on the other hand, allows a client application, be it web, mobile, or Emacs, to communicate with the server so a user can actually use the service.

An implementation may support one or both of those layers so that we may create a complete set of a server with a UI, but it’s also completely valid to have an entirely automated instance without any human interaction.

I won’t dissect the entire standard; I only want to grasp the general mechanics.


In ActivityPub, a “user” is represented as an Actor on a given server. The same person may have identical accounts on multiple servers, but each of those accounts is a separate Actor7

Servers in ActivityPub communicate via simple REST requests.

Each Actor has unique endpoints representing:


When a User wants to send a message to the world:

Public message sendout
Public message sendout
  1. User A’s client sends a POST message to their own outbox. The message has left the client and is ready to be delivered to a different server.
  2. Any server can call the outbox with a GET request. This is how public messages are delivered between servers.
  3. Users on that server can then read the message in their own inbox.

When User A wants to send a message to User B:

Private message exchange
Private message exchange
  1. User A’s client sends a POST message to their own outbox. The message has left the client and is ready to be delivered to a different server.
  2. User A’s server sends a POST message to the inbox of User B. The message is delivered to the Actor.
  3. User B can then call GET on their inbox to read it. The message is delivered to a Client.

Those requests are authenticated as a given Actor so that we can read only messages addressed to this user. The messages are addressed via “collections” - an Outbox is a collection, an Inbox is a collection, or a follower list is a collection.

The server knows who a given Actor is following, so only messages accessible by any user on this server will be fetched.

There is also a special “Public” collection, void of permissions. Any user on any server can fetch any message sent to “fPublic” without any authentication. This is how federated messages in Mastodon are propagated - someone follows a user on a different instance, so the person’s server knows about the outbox collection and can fetch messages. Since it’s aimed at the public, it will be available to each user on this server.

We now know how private and public messages are propagated.


Outbox and inbox don’t contain the messages, but rather Activities. An activity is a request to Create a message, Edit it, Delete it, and so on. This mechanism allows users to edit their messages; in time, all servers should display the latest version.


ActivityPub is interesting as it allows for a decentralized social network closer to how Email works than something like Twitter. However, with this comes two downsides:

There’s much more to unpack here, but this is something for people developing software using ActivityPub. I am not yet one of those brave folks.

  1. Michal Sapka’s blog on Twitter ↩︎

  2. mastodon.el code repository ↩︎

  3. https://bsd.network/@rubenerd ↩︎

  4. W3C ActivityPub Standard text ↩︎

  5. There’s even a website listing services on the Fediverse. ↩︎

  6. W3C Activity Streams 2.0 standard text↩︎

  7. I have yet to learn about any mechanism preventing abuse here. Anyone can create an account with the same username on a server I don’t use and pose as me. Some Web of Trust here would be very beneficial. ↩︎