How to Make Activity Delivery Look Fast with ActivityPub
One of the hard things about delivering activities in a social network is making it seem like the subscriber receives the published object (image, video, text, like) almost immediately after the publisher posts it. You can only get two out of three of these things:
- Near-realtime delivery
- Large audience lists
- Low server resources
I call this Prodromou’s Triangle, although it probably already has a name.
The important thing for people writing ActivityPub software is that you don’t really need near-realtime delivery. Most people aren’t on their Mastodon client 24x7x365; they check once every few hours, daily, or less frequently. So, busting your ass to deliver to everyone in under a few seconds is a waste of your effort.
If delivery is going to take a non-trivial amount of time, you should focus on delivering to the people who are going to notice first. So, don’t loop through your addressee list in alphabetical order from firstname.lastname@example.org down to email@example.com. Don’t just take addresses in the random order your database gives them to you. Order them from most likely to notice and complain to least likely.
Here’s a rough ordering of who’s going to notice any delivery delays:
The author. Get it to their inbox and profile ASAP.
Connected addressees. Are any of the addressees currently connected? Send to them next.
Unconnected addressees. Catch up the other addressees next.
Connected local subscribers. They’re more likely to see it, anyway.
Local public timelines. Local and federated, hashtag and search.
Connected remote subscribers. If they’re online, they’re going to notice, so get it to them next.
Public timeline feeds. If you provide remote subscription for your public timeline(s), push now.
Unconnected local subscribers. They’ll get it next time they log in.
Unconnected remote subscribers. They’ll read it some other time.
How can you tell the difference between “connected” and “unconnected” addresses?
- If they’re local, you can use WebSocket connection status as a sign that they’re connected. If you don’t support WebSockets, you can use last API call, or last Web hit as a proxy.
- If they’re remote, it’s harder, but you can use last-seen-activity as a proxy. Someone who just liked a photo a few seconds ago is probably still online. Someone who last commented in 2019 probably doesn’t need sub-10-second delivery.
The nice part of this ranking is that it handles direct-messaging pretty nicely. DMs usually go out to a small (<10) group of people, so just delivering to the author and addressees should be quite quick.
I’m happy to hear of other tricks for getting things delivered fast with AP.