diff --git a/api/funkwhale_api/federation/activity.py b/api/funkwhale_api/federation/activity.py
index af31b8c5afb7a282fb9fa35a3c4c57b551d04274..becf6c96f55b68d2503eb7442f673e0fadb4cef7 100644
--- a/api/funkwhale_api/federation/activity.py
+++ b/api/funkwhale_api/federation/activity.py
@@ -1,18 +1,5 @@
-import logging
-import json
-import requests_http_signature
-import uuid
-
-from django.conf import settings
-
-from funkwhale_api.common import session
-from funkwhale_api.common import utils as funkwhale_utils
-
-from . import models
 from . import serializers
-from . import signing
-
-logger = logging.getLogger(__name__)
+from . import tasks
 
 ACTIVITY_TYPES = [
     'Accept',
@@ -65,31 +52,16 @@ OBJECT_TYPES = [
 
 
 def deliver(activity, on_behalf_of, to=[]):
-    from . import actors
-    logger.info('Preparing activity delivery to %s', to)
-    auth = signing.get_auth(
-        on_behalf_of.private_key, on_behalf_of.private_key_id)
-    for url in to:
-        recipient_actor = actors.get_actor(url)
-        logger.debug('delivering to %s', recipient_actor.inbox_url)
-        logger.debug('activity content: %s', json.dumps(activity))
-        response = session.get_session().post(
-            auth=auth,
-            json=activity,
-            url=recipient_actor.inbox_url,
-            timeout=5,
-            verify=settings.EXTERNAL_REQUESTS_VERIFY_SSL,
-            headers={
-                'Content-Type': 'application/activity+json'
-            }
-        )
-        response.raise_for_status()
-        logger.debug('Remote answered with %s', response.status_code)
+    return tasks.send.delay(
+        activity=activity,
+        actor_id=on_behalf_of.pk,
+        to=to
+    )
 
 
 def accept_follow(follow):
     serializer = serializers.AcceptFollowSerializer(follow)
-    deliver(
+    return deliver(
         serializer.data,
         to=[follow.actor.url],
         on_behalf_of=follow.target)
diff --git a/api/funkwhale_api/federation/tasks.py b/api/funkwhale_api/federation/tasks.py
index 03124d16bc74d3329bc2c3b32bd8da97d7e302bd..5140eff6ed4e48e7a8590b7ae4c0f96da7b188f1 100644
--- a/api/funkwhale_api/federation/tasks.py
+++ b/api/funkwhale_api/federation/tasks.py
@@ -1,9 +1,48 @@
+import json
+import logging
+
+from django.conf import settings
+
 from requests.exceptions import RequestException
 
+from funkwhale_api.common import session
 from funkwhale_api.taskapp import celery
 
+from . import actors
 from . import library as lb
 from . import models
+from . import signing
+
+
+logger = logging.getLogger(__name__)
+
+
+@celery.app.task(
+    name='federation.send',
+    autoretry_for=[RequestException],
+    retry_backoff=30,
+    max_retries=5)
+@celery.require_instance(models.Actor, 'actor')
+def send(activity, actor, to):
+    logger.info('Preparing activity delivery to %s', to)
+    auth = signing.get_auth(
+        actor.private_key, actor.private_key_id)
+    for url in to:
+        recipient_actor = actors.get_actor(url)
+        logger.debug('delivering to %s', recipient_actor.inbox_url)
+        logger.debug('activity content: %s', json.dumps(activity))
+        response = session.get_session().post(
+            auth=auth,
+            json=activity,
+            url=recipient_actor.inbox_url,
+            timeout=5,
+            verify=settings.EXTERNAL_REQUESTS_VERIFY_SSL,
+            headers={
+                'Content-Type': 'application/activity+json'
+            }
+        )
+        response.raise_for_status()
+        logger.debug('Remote answered with %s', response.status_code)
 
 
 @celery.app.task(
diff --git a/api/tests/federation/test_activity.py b/api/tests/federation/test_activity.py
index dbd60bbd7cee0ad363a21275083eafffc3949de7..c2673ff3bd1ff18f7cb1f2486c2e18516e36d86d 100644
--- a/api/tests/federation/test_activity.py
+++ b/api/tests/federation/test_activity.py
@@ -4,12 +4,13 @@ from funkwhale_api.federation import activity
 from funkwhale_api.federation import serializers
 
 
-def test_deliver(nodb_factories, r_mock, mocker):
-    to = nodb_factories['federation.Actor']()
+def test_deliver(factories, r_mock, mocker, settings):
+    settings.CELERY_TASK_ALWAYS_EAGER = True
+    to = factories['federation.Actor']()
     mocker.patch(
         'funkwhale_api.federation.actors.get_actor',
         return_value=to)
-    sender = nodb_factories['federation.Actor']()
+    sender = factories['federation.Actor']()
     ac = {
         'id': 'http://test.federation/activity',
         'type': 'Create',