diff --git a/oslo_messaging/rpc/dispatcher.py b/oslo_messaging/rpc/dispatcher.py
index 71111b57d..0277d8e3a 100644
--- a/oslo_messaging/rpc/dispatcher.py
+++ b/oslo_messaging/rpc/dispatcher.py
@@ -111,7 +111,7 @@ class RPCDispatcher(object):
 
     @staticmethod
     def _is_namespace(target, namespace):
-        return namespace == target.namespace
+        return namespace in target.accepted_namespaces
 
     @staticmethod
     def _is_compatible(target, version):
diff --git a/oslo_messaging/target.py b/oslo_messaging/target.py
index f37a2b296..e91cc878a 100644
--- a/oslo_messaging/target.py
+++ b/oslo_messaging/target.py
@@ -57,16 +57,23 @@ class Target(object):
       servers listening on a topic by setting fanout to ``True``, rather than
       just one of them.
     :type fanout: bool
+    :param legacy_namespaces: A server always accepts messages specified via
+      the 'namespace' parameter, and may also accept messages defined via
+      this parameter. This option should be used to switch namespaces safely
+      during rolling upgrades.
+    :type legacy_namespaces: list of strings
     """
 
     def __init__(self, exchange=None, topic=None, namespace=None,
-                 version=None, server=None, fanout=None):
+                 version=None, server=None, fanout=None,
+                 legacy_namespaces=None):
         self.exchange = exchange
         self.topic = topic
         self.namespace = namespace
         self.version = version
         self.server = server
         self.fanout = fanout
+        self.accepted_namespaces = [namespace] + (legacy_namespaces or [])
 
     def __call__(self, **kwargs):
         for a in ('exchange', 'topic', 'namespace',
diff --git a/oslo_messaging/tests/rpc/test_dispatcher.py b/oslo_messaging/tests/rpc/test_dispatcher.py
index edc4e7e0a..32e0b09c5 100644
--- a/oslo_messaging/tests/rpc/test_dispatcher.py
+++ b/oslo_messaging/tests/rpc/test_dispatcher.py
@@ -89,6 +89,18 @@ class TestDispatcher(test_utils.BaseTestCase):
               dispatch_to=None,
               ctxt={}, msg=dict(method='foo', version='3.2'),
               success=False, ex=oslo_messaging.UnsupportedVersion)),
+        ('message_in_null_namespace_with_multiple_namespaces',
+         dict(endpoints=[dict(namespace='testns',
+                              legacy_namespaces=[None])],
+              dispatch_to=dict(endpoint=0, method='foo'),
+              ctxt={}, msg=dict(method='foo', namespace=None),
+              success=True, ex=None)),
+        ('message_in_wrong_namespace_with_multiple_namespaces',
+         dict(endpoints=[dict(namespace='testns',
+                              legacy_namespaces=['second', None])],
+              dispatch_to=None,
+              ctxt={}, msg=dict(method='foo', namespace='wrong'),
+              success=False, ex=oslo_messaging.UnsupportedVersion)),
     ]
 
     def test_dispatcher(self):