How to Maybe Build a Social Media Platform

From Someone Who Failed


This is a companion to my How to Not Build a Social Media Platform, which looks at some of the issues related to building microblogging-style "slow" social media platforms. In summary, scale is preferred in the design over all other possible attributes. These decentralized platforms believe they are in a zero-sum competition with the centralized establishment. This just is not true. And believing in this leads to designs which over-emphasize scale, overly public points-of-view, and de-emphasizes privacy and safety. These spaces are largely unmoderated and only occasionally community-driven.

Again, I love these really problematic social platforms. They are a lot of fun. I founded rstat.us, a federated social media platform that catered to a small tens of thousands of accounts. I have been a part of the standardization of ActivityStreams and ActivityPub, which are protocols used in Mastodon and similar federated social platforms. I help fund Mastodon via Patreon. Am I part of the problem? MAYBE.

Here, I will elaborate more on the solution space. The main goal is a private-by-default platform with very intentional audience targetting. You should know who will see a post and what people can do with it. For reasons of governance, data ownership, and privacy, the platform should be federated and self-hosted.

These are high-level goals, of course, and it is one thing to just list them. Many really do not believe such a platform is possible or that folks will never migrate to such a platform. There is some stubborn notion that people really want the Twitter model: a all-encompassing public feed of everything everyone is saying where anybody in the world can react to you or talk to you as soon as you join. That is a nightmare. It is absolutely not the only way. I will tackle these critiques as they become relevant through this design discussion.

Point-of-View

The conventional point-of-view of a social media platform is often thought to be the individual user. I posit the point-of-view of Twitter, StatusNet, rstat.us, Mastodon, etc is the world. It is very "abyss looking back" more than it is any ability to shout to the abyss and get a coherent response. This is the crux of the moderation issue and the double-edged sword of Metcalfe's Law. Your moderation problem becomes true for all people, all at once, with no place of refuge for anybody vulnerable to go. So they leave! A burden that only increases with scale.

The way to alter the point-of-view in such systems is to do audience targetting. In this mode, you write a post and direct it to one or more groups. These groups might be devised of your friends, or based on a topic of interest, or an organization. The visibility of a post is kept to those who are subscribed to that group.

Yes, basically Google+ had the right idea. However, groups are created organically instead of being a named list of contacts. A group is created whenever somebody posts to a unique name. The post then is discoverable via that group, which aggregates such posts. You are, then, also only discoverable by those also included in those groups.

Group based discovery is beneficial over public discovery due to the ability to direct your audience to those who are more likely to engage in a predictable way. It will avoid some manner of purposeful targetted harassment. Moderation can be done within the group instead of somehow enforcing one set of rules of conduct on every post en masse. Groups can be made small and very difficult to discover if given complex names.

Private-by-Default

Once you have some form of audience targetting, it is easier to imagine a system where posts are private-by-default. You purposefully select the audience for a message, and in doing so transform a post from the vacuum and open it to your audience. Conversely, traditional systems are public-by-default. Your post goes to the world unless there is some means to restrict it. Those systems are designed to function best if your content is seen by everybody.

The motivations for a public-by-default are notorious, in my view. They come from a capitalistic mindset that sees content as profit and wants to sell it. In return, you are promised a platform for self-expression and self-promotion. There is logic to it, which is why it is often seen as a critique of private systems compared to public blogs. And nothing stops the audience targetting from selecting "worldwide" as a group, so we do not lose it. The difference is we are not pushing for this worldview.

Proponents of a private-by-default system do not believe that every person requires a platform that is so widely open. Even self-promotion is more beneficial if you are targetting your audience. If I am writing a short story, it might be better to announce it toward an audience that can appreciate it instead of competing with every single post in the entire world. This is what "hashtags" originally solved, so it does not seem like a dramatic shift to suggest that topic of interest be the point-of-view for new content.

Federation

There is this notion that private systems do not require federation. I have studied distributed systems for over a decade and I do not understand any of that logic! Of course a system with tiers of audiences of differing sizes can and should federate.

Federation is the notion that an actor on one system can act as itself on an independent system. That is really all there is to it. If I am "wilkie" on mastodon.social, I can follow somebody on "queer.zone" and I can like a post on "glammr.us". Technically, I might even get a permission to post on "slime.global" as my own actor, but I do not believe any social media platform currently allows this. My posts have a verifiable point of origin, a space I can control myself if I wish, that determines its representation, which allows it to be represented accurately on a different system as though it were posted there instead.

Federation yields benefits to all sizes of system. It does not make large systems possible. The largest systems are centralized, in fact, so we know the distribution of logic and mechanics that federation provides is unnecessary. What it does do is it allows identity to be separate from both content and control. It allows migration of actions from one node to another. It allows self-hosted instances where people control the apparatus that posts and stores/owns their content.

One reason that public-facing actor-oriented systems are so prevalent might be that they are the easiest designs to implement. You have a feed for each actor. The feed exists at one originating and well-known location such as "mastodon.org/@wilkie", but might be relayed or mirrored for the sake of performance. You subscribe to one of more of such feeds. You have an obvious means of aggregating a timeline of content by polling each feed from its well-known location.

With a group-oriented design, you have one step of indirection. You must aggregate a feed without an origin. A group has no well-known location. It is a set of disparate content. How does one aggregate such a feed?

Well... that's a lot of fun, actually.

A little bit of Math and Magic.

Implementation

For this design, you no longer have a polling system of feeds. You have a gossiping system of tokens. Most of this can be derived using a fairly traditional distribute hash table. The table would be augmented to store lists of tokens as data.

If you devise a post to go to the #retrocomputing group, then your post would become a payload under the hashed token for that group. The post itself would also be hashed and stored in a distributed store. Each group would have a unique token that represents it. The group aggregation metadata which contains the known posts that are within it is stored in the distributed store.

Several functions are required. lookup(token) is a traditional distributed hash lookup for a particular token. This will respond with the location(s) of the data for that token. For groups, the data is a list of post tokens for a particular time range and possibly a key for the group, which we will ignore for now. For posts, the data is an encoded representation and an author token. For an author, the data is the public key for that actor.

Using the public key for the actor and potentially the group, one can decode the post and render it. Since the distributed store might report several locations for the group data, it might aggregate it. To ensure that the group is properly distributed, it may be further subdivided into time ranges. Page propagation and discovery might require multiple lookups for the group to present a timeline.

The post(data, actor, group) function creates a post where the group parameter is the token for the group. It is trivial to encode the token for the group since it is a simple hash of the name of the group and possibly a starting date to allow for larger groups. The data is encoded with the private key given by actor and the payload then includes a hash of the public key for the actor. The payload is itself hashed, which consists of the content and the actor hash, and stored in the distributed store as an item in the group's list.

There is no original location for any such data and it is at the whim of propagation. Many tokens are constantly restored, such as actor public keys. That is, they can be rewritten and overwritten on every post which somewhat ensures they are present. Data might be lost, perhaps purposefully so. Conforming nodes in the distributed store could certainly delete their payloads upon request. Generally, good distributed stores will not lose new data as they can mirror to older nodes. It is not really a good to ensure longevity. Archive systems can exist for this purpose.

Actions upon posts can be implemented on top of this framework. If one makes an action on a post, it is similar to creating a post with the group name of #retrocomputing‑like‑{post‑token} where posting an action to that can be queried and rendered upon request. This allows such actions to require a secondary key that represents a capability to perform that action. For instance, the group name for the actions might be obscured. It might be #retrocomputing‑like‑{post‑token}‑{random‑hash}. If this is not present on your post payload, this effectively prevents that action on your post.

A capability model is much more possible in such a polling system. The name of the bucket that your post targets is essentially private knowledge and serves as the capability required to act. Obscuring the name of the group or requiring a shared key to post within a group also suffices as a capability to post within a particular space. This is useful for leveraging the system at large to create private spaces and private modes of communication. Another reason federation is useful in private systems! People neglect to consider encrypted traffic as usefully federated by collaborating parties that cannot read it.

The post payloads can be ActivityStreams messages.

This style of system where content is always aggregated by topic resembles several chat systems. These platforms, such as Discord, Matrix, and even IRC, give some ability to target an audience. Moderation happens per group (room/channel/etc) and is done by communal effort by participants of that group.

The difference is the style of communication. These are all real-time linear platforms. They are chat services that greatly imply a single topic of discussion at a time and not a feed of disparate content fitting the theme. There does need to be a different and intentional design for the slower form of communication used by a microblogging platform.

Matrix does aggregate posts to the room they are within and encrypts them such that only members of the room can read them. This is a similar process to this advocated platform, and there is much to reuse from this. Rooms have a homeserver, however, and therefore have an origin. This makes sense since there needs to be an authority for preserving the consistency of ordering. You need somebody to decide when a message happened and to decide what order messages appear. This is something worth avoiding in a decentralized design when there is no strict ordering required.

Use Cases

I am knitting a sweater and want to post my progress. I upload an image and a short message "Hey! I'm making good progress and I'm loving this color!" I tag the audience as: #friends‑34fz53gs4, #knitting, #diy. These groups aggregate this post. When my friend Alice pulls the #friends‑34fz53gs4 feed, which I previously invited her to do, she will see my post and can interact with it. When Bob views the #diy feed, he might see my post and interact with it. This is the first time Bob has seen any of my posts and has now discovered my content and might elect to view all my posts that are within the #diy tag. A group only sees what it has aggregated.

I am writing a note for myself. I simply write "Hello world" and send it without a group. It can be seen by me and only me. Since there is no targetting, no group and no other person can ever decode it and read it.

I am writing a note for everybody. I write "The world is a vampire!" and target with the arbitrary group #worldwide. People who elect to see this feed will see your message, if at all possible for them to witness. There is likely no moderation on such a large group.

Problems

Targetted harassment of publicly known groups can occur when messages are spammed in some way.

Group lists are currently not encoded in any way. Any known group, even with encrypted content, one can at least query the number of items even if one cannot read them. The name of the group being obscured is useful.

Private groups offer a shared key in order to participate. This allows revocation of such a key to oust members of the group and to invite new members without necessarily ceding much control. Yet, revocation does not affect the reading of historic posts and may require generation of new keys for all members of a group for new posts. This feels like a hard problem.

This capability-based system might split the fediverse since the overall federation in place currently is not capability based. It is possible perhaps to bridge the two and have a "public" fediverse that works the traditional way and is invoked when you publish certain posts with that level of visibility.

For Fun

Since you no longer have an actor-originating scheme where there is a well-known location for content, you could technically do this entirely client-side. A little WebRTC here, a little IndexedDB there, and what do you know. You need a point of entry or two to seed and bootstrap entry to the network, but then you have something going. Of course, NAT/ICE/etc problems will absolutely plague you, so you'll probably need a vaguely centralized proxy, but it would be fun!

References

Tags

programming, programming/ethics, social

Comments

If you'd like to comment, just send me an email at wilkie@xomb.org or on either Twitter or via my Mastodon profile. I would love to hear from you! Any opinions, criticism, etc are welcome.

Donations

If you'd like to make a donation, I don't know what is best for that. Let me know.

Copyright

All content off of this domain, unless otherwise noted or linked from a different domain, is licensed as CC0