diff --git a/django/db/models/base.py b/django/db/models/base.py
--- a/django/db/models/base.py
+++ b/django/db/models/base.py
@@ -456,7 +456,7 @@
             meta = cls._meta
 
         if origin and not meta.auto_created:
-            signals.pre_save.send(sender=origin, instance=self, raw=raw)
+            signals.pre_save.send(sender=origin, instance=self, raw=raw, using=using)
 
         # If we are in a raw save, save the object exactly as presented.
         # That means that we don't try to be smart about saving attributes
@@ -540,7 +540,7 @@
         # Signal that the save is complete
         if origin and not meta.auto_created:
             signals.post_save.send(sender=origin, instance=self,
-                created=(not record_exists), raw=raw)
+                created=(not record_exists), raw=raw, using=using)
 
     save_base.alters_data = True
 
diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py
--- a/django/db/models/fields/related.py
+++ b/django/db/models/fields/related.py
@@ -566,7 +566,7 @@
                     # duplicate data row for symmetrical reverse entries.
                     signals.m2m_changed.send(sender=rel.through, action='pre_add',
                         instance=self.instance, reverse=self.reverse,
-                        model=self.model, pk_set=new_ids)
+                        model=self.model, pk_set=new_ids, using=db)
                 # Add the ones that aren't there already
                 for obj_id in new_ids:
                     self.through._default_manager.using(db).create(**{
@@ -578,7 +578,7 @@
                     # duplicate data row for symmetrical reverse entries.
                     signals.m2m_changed.send(sender=rel.through, action='post_add',
                         instance=self.instance, reverse=self.reverse,
-                        model=self.model, pk_set=new_ids)
+                        model=self.model, pk_set=new_ids, using=db)
 
         def _remove_items(self, source_field_name, target_field_name, *objs):
             # source_col_name: the PK colname in join_table for the source object
@@ -594,14 +594,16 @@
                         old_ids.add(obj.pk)
                     else:
                         old_ids.add(obj)
+                # Work out what DB we're operating on
+                db = router.db_for_write(self.through.__class__, instance=self.instance)
+                # Send a signal to the other end if need be.
                 if self.reverse or source_field_name == self.source_field_name:
                     # Don't send the signal when we are deleting the
                     # duplicate data row for symmetrical reverse entries.
                     signals.m2m_changed.send(sender=rel.through, action="pre_remove",
                         instance=self.instance, reverse=self.reverse,
-                        model=self.model, pk_set=old_ids)
+                        model=self.model, pk_set=old_ids, using=db)
                 # Remove the specified objects from the join table
-                db = router.db_for_write(self.through.__class__, instance=self.instance)
                 self.through._default_manager.using(db).filter(**{
                     source_field_name: self._pk_val,
                     '%s__in' % target_field_name: old_ids
@@ -611,17 +613,17 @@
                     # duplicate data row for symmetrical reverse entries.
                     signals.m2m_changed.send(sender=rel.through, action="post_remove",
                         instance=self.instance, reverse=self.reverse,
-                        model=self.model, pk_set=old_ids)
+                        model=self.model, pk_set=old_ids, using=db)
 
         def _clear_items(self, source_field_name):
+            db = router.db_for_write(self.through.__class__, instance=self.instance)
             # source_col_name: the PK colname in join_table for the source object
             if self.reverse or source_field_name == self.source_field_name:
                 # Don't send the signal when we are clearing the
                 # duplicate data rows for symmetrical reverse entries.
                 signals.m2m_changed.send(sender=rel.through, action="pre_clear",
                     instance=self.instance, reverse=self.reverse,
-                    model=self.model, pk_set=None)
-            db = router.db_for_write(self.through.__class__, instance=self.instance)
+                    model=self.model, pk_set=None, using=db)
             self.through._default_manager.using(db).filter(**{
                 source_field_name: self._pk_val
             }).delete()
@@ -630,7 +632,7 @@
                 # duplicate data rows for symmetrical reverse entries.
                 signals.m2m_changed.send(sender=rel.through, action="post_clear",
                     instance=self.instance, reverse=self.reverse,
-                    model=self.model, pk_set=None)
+                    model=self.model, pk_set=None, using=db)
 
     return ManyRelatedManager
 
diff --git a/django/db/models/query.py b/django/db/models/query.py
--- a/django/db/models/query.py
+++ b/django/db/models/query.py
@@ -1311,7 +1311,8 @@
             # Pre-notify all instances to be deleted.
             for pk_val, instance in items:
                 if not cls._meta.auto_created:
-                    signals.pre_delete.send(sender=cls, instance=instance)
+                    signals.pre_delete.send(sender=cls, instance=instance,
+                        using=using)
 
             pk_list = [pk for pk,instance in items]
 
@@ -1343,7 +1344,7 @@
                         setattr(instance, field.attname, None)
 
                 if not cls._meta.auto_created:
-                    signals.post_delete.send(sender=cls, instance=instance)
+                    signals.post_delete.send(sender=cls, instance=instance, using=using)
                 setattr(instance, cls._meta.pk.attname, None)
 
         if forced_managed:
diff --git a/django/db/models/signals.py b/django/db/models/signals.py
--- a/django/db/models/signals.py
+++ b/django/db/models/signals.py
@@ -5,12 +5,12 @@
 pre_init = Signal(providing_args=["instance", "args", "kwargs"])
 post_init = Signal(providing_args=["instance"])
 
-pre_save = Signal(providing_args=["instance", "raw"])
-post_save = Signal(providing_args=["instance", "raw", "created"])
+pre_save = Signal(providing_args=["instance", "raw", "using"])
+post_save = Signal(providing_args=["instance", "raw", "created", "using"])
 
-pre_delete = Signal(providing_args=["instance"])
-post_delete = Signal(providing_args=["instance"])
+pre_delete = Signal(providing_args=["instance", "using"])
+post_delete = Signal(providing_args=["instance", "using"])
 
 post_syncdb = Signal(providing_args=["class", "app", "created_models", "verbosity", "interactive"])
 
-m2m_changed = Signal(providing_args=["action", "instance", "reverse", "model", "pk_set"])
+m2m_changed = Signal(providing_args=["action", "instance", "reverse", "model", "pk_set", "using"])
diff --git a/docs/ref/signals.txt b/docs/ref/signals.txt
--- a/docs/ref/signals.txt
+++ b/docs/ref/signals.txt
@@ -113,6 +113,9 @@
     ``instance``
         The actual instance being saved.
 
+    ``using``
+        The database alias being used.
+
 post_save
 ---------
 
@@ -133,6 +136,9 @@
     ``created``
         A boolean; ``True`` if a new record was created.
 
+    ``using``
+        The database alias being used.
+
 pre_delete
 ----------
 
@@ -150,6 +156,9 @@
     ``instance``
         The actual instance being deleted.
 
+    ``using``
+        The database alias being used.
+
 post_delete
 -----------
 
@@ -170,6 +179,9 @@
         Note that the object will no longer be in the database, so be very
         careful what you do with this instance.
 
+    ``using``
+        The database alias being used.
+
 m2m_changed
 -----------
 
@@ -228,6 +240,9 @@
 
         For the ``"clear"`` action, this is ``None``.
 
+    ``using``
+        The database alias being used.
+
 For example, if a ``Pizza`` can have multiple ``Topping`` objects, modeled
 like this:
 
@@ -266,6 +281,8 @@
                     ``Pizza``)
 
     ``pk_set``      ``[t.id]`` (since only ``Topping t`` was added to the relation)
+	
+	``using``       ``"default"`` (since the default router sends writes here)
     ==============  ============================================================
 
 And if we would then do something like this:
@@ -293,6 +310,8 @@
 
     ``pk_set``      ``[p.id]`` (since only ``Pizza p`` was removed from the
                     relation)
+	
+	``using``       ``"default"`` (since the default router sends writes here)
     ==============  ============================================================
 
 class_prepared
diff --git a/tests/modeltests/signals/models.py b/tests/modeltests/signals/models.py
--- a/tests/modeltests/signals/models.py
+++ b/tests/modeltests/signals/models.py
@@ -11,6 +11,10 @@
     def __unicode__(self):
         return u"%s %s" % (self.first_name, self.last_name)
 
+class Project(models.Model):
+    people = models.ManyToManyField(Person)
+
+
 def pre_save_test(signal, sender, instance, **kwargs):
     print 'pre_save signal,', instance
     if kwargs.get('raw'):
diff --git a/tests/modeltests/signals/tests.py b/tests/modeltests/signals/tests.py
--- a/tests/modeltests/signals/tests.py
+++ b/tests/modeltests/signals/tests.py
@@ -1,8 +1,12 @@
 from django.db.models import signals
+from django.db import DEFAULT_DB_ALIAS, router
 from django.test import TestCase
-from modeltests.signals.models import Person
+from modeltests.signals.models import Person, Project
 
-class MyReceiver(object):
+class DisconnectReceiver(object):
+    """
+    Used to test the disconnection of signals.
+    """
     def __init__(self, param):
         self.param = param
         self._run = False
@@ -10,14 +14,40 @@
     def __call__(self, signal, sender, **kwargs):
         self._run = True
         signal.disconnect(receiver=self, sender=sender)
+ 
+class DatabaseReceiver(object):
+    """
+    Used in the tests for the database argument in signals (#13552)
+    """
+    def __call__(self, signal, sender, **kwargs):
+        self._database = kwargs['using']
+    
+class TestRouter(object):
+    """
+    A router that sends all writes to the other database.
+    """
+    def db_for_write(self, model, **hints):
+        return "other"
 
 class SignalTests(TestCase):
+    
+    multi_db = True
+    
+    def _write_to_other(self):
+        "Sends all writes to 'other'."
+        self.old_routers = router.routers
+        router.routers = [TestRouter()]
+
+    def _write_to_default(self):
+        "Sends all writes to the default DB"
+        router.routers = self.old_routers
+    
     def test_disconnect_in_dispatch(self):
         """
         Test that signals that disconnect when being called don't mess future
         dispatching.
         """
-        a, b = MyReceiver(1), MyReceiver(2)
+        a, b = DisconnectReceiver(1), DisconnectReceiver(2)
         signals.post_save.connect(sender=Person, receiver=a)
         signals.post_save.connect(sender=Person, receiver=b)
         p = Person.objects.create(first_name='John', last_name='Smith')
@@ -25,4 +55,68 @@
         self.failUnless(a._run)
         self.failUnless(b._run)
         self.assertEqual(signals.post_save.receivers, [])
-        
+    
+    def test_database_arg_save_and_delete(self):
+        """
+        Tests that the pre/post_save signal contains the correct database.
+        (#13552)
+        """
+        # Make some signal receivers
+        pre_save_receiver = DatabaseReceiver()
+        post_save_receiver = DatabaseReceiver()
+        pre_delete_receiver = DatabaseReceiver()
+        post_delete_receiver = DatabaseReceiver()
+        # Make model and connect receivers
+        signals.pre_save.connect(sender=Person, receiver=pre_save_receiver)
+        signals.post_save.connect(sender=Person, receiver=post_save_receiver)
+        signals.pre_delete.connect(sender=Person, receiver=pre_delete_receiver)
+        signals.post_delete.connect(sender=Person, receiver=post_delete_receiver)
+        p = Person.objects.create(first_name='Darth', last_name='Vader')
+        # Save and test receivers got calls
+        p.save()
+        self.assertEqual(pre_save_receiver._database, DEFAULT_DB_ALIAS)
+        self.assertEqual(post_save_receiver._database, DEFAULT_DB_ALIAS)
+        # Delete, and test
+        p.delete()
+        self.assertEqual(pre_delete_receiver._database, DEFAULT_DB_ALIAS)
+        self.assertEqual(post_delete_receiver._database, DEFAULT_DB_ALIAS)
+        # Save again to a different database
+        p.save(using="other")
+        self.assertEqual(pre_save_receiver._database, "other")
+        self.assertEqual(post_save_receiver._database, "other")
+        # Delete, and test
+        p.delete(using="other")
+        self.assertEqual(pre_delete_receiver._database, "other")
+        self.assertEqual(post_delete_receiver._database, "other")
+    
+    def test_database_arg_m2m(self):
+        """
+        Test that the m2m_changed signal has a correct database arg (#13552)
+        """
+        # Make a receiver
+        receiver = DatabaseReceiver()
+        # Connect it, and make the models
+        signals.m2m_changed.connect(receiver=receiver)
+        pe = Person.objects.create(first_name='Jane', last_name='Smith')
+        pr = Project.objects.create()
+        # Test addition
+        pr.people.add(pe)
+        self.assertEqual(receiver._database, DEFAULT_DB_ALIAS)
+        self._write_to_other()
+        pr.people.add(pe)
+        self._write_to_default()
+        self.assertEqual(receiver._database, "other")
+        # Test removal
+        pr.people.remove(pe)
+        self.assertEqual(receiver._database, DEFAULT_DB_ALIAS)
+        self._write_to_other()
+        pr.people.remove(pe)
+        self._write_to_default()
+        self.assertEqual(receiver._database, "other")
+        # Test clearing
+        pr.people.clear()
+        self.assertEqual(receiver._database, DEFAULT_DB_ALIAS)
+        self._write_to_other()
+        pr.people.clear()
+        self._write_to_default()
+        self.assertEqual(receiver._database, "other")
\ No newline at end of file
