Fedify: an ActivityPub server framework<p>Coming soon in <a class="mention hashtag" rel="nofollow noopener noreferrer" href="https://hollo.social/tags/Fedify" target="_blank">#<span>Fedify</span></a> 1.5.0: Smart fan-out for efficient activity delivery!</p><p>After getting feedback about our queue design, we're excited to introduce a significant improvement for accounts with large follower counts.</p><p>As we discussed in <a href="https://hollo.social/@fedify/0195802b-35d0-7a9b-a8f8-92e3035415d8" rel="nofollow noopener noreferrer" target="_blank">our previous post</a>, Fedify currently creates separate queue messages for each recipient. While this approach offers excellent reliability and individual retry capabilities, it causes performance issues when sending activities to thousands of followers.</p><p>Our solution? A new two-stage “fan-out” approach:</p><ol>
<li>When you call <code>Context.sendActivity()</code>, we'll now enqueue just <em>one</em> consolidated message containing your activity payload and recipient list</li><li>A background worker then processes this message and re-enqueues individual delivery tasks</li>
</ol><p>The benefits are substantial:</p><ul>
<li><code>Context.sendActivity()</code> returns almost instantly, even for massive follower counts</li><li>Memory usage is dramatically reduced by avoiding payload duplication</li><li>UI responsiveness improves since web requests complete quickly</li><li>The same reliability for individual deliveries is maintained</li>
</ul><p>For developers with specific needs, we're adding a <a href="https://unstable.fedify.dev/manual/send#when-to-use-each-option" rel="nofollow noopener noreferrer" target="_blank"><code>fanout</code> option</a> with three settings:</p><ul>
<li><code>"auto"</code> (default): Uses fanout for large recipient lists, direct delivery for small ones</li><li><code>"skip"</code>: Bypasses fanout when you need different payload per recipient</li><li><code>"force"</code>: Always uses fanout even with few recipients</li>
</ul><pre><code>// Example with custom fanout setting
await ctx.sendActivity(
{ identifier: "alice" },
recipients,
activity,
{ fanout: "skip" } // Directly enqueues individual messages
);
</code></pre><p>This change represents months of performance testing and should make Fedify work beautifully even for extremely popular accounts!</p><p>For more details, check out our <a href="https://unstable.fedify.dev/manual/send#optimizing-activity-delivery-for-large-audiences" rel="nofollow noopener noreferrer" target="_blank">docs</a>.</p><p>What other <a class="mention hashtag" rel="nofollow noopener noreferrer" href="https://hollo.social/tags/performance" target="_blank">#<span>performance</span></a> optimizations would you like to see in future Fedify releases?</p><p><a class="mention hashtag" rel="nofollow noopener noreferrer" href="https://hollo.social/tags/ActivityPub" target="_blank">#<span>ActivityPub</span></a> <a class="mention hashtag" rel="nofollow noopener noreferrer" href="https://hollo.social/tags/fedidev" target="_blank">#<span>fedidev</span></a></p>