diff --git a/django/contrib/sessions/backends/base.py b/django/contrib/sessions/backends/base.py
--- a/django/contrib/sessions/backends/base.py
+++ b/django/contrib/sessions/backends/base.py
@@ -33,6 +33,7 @@
     """
     TEST_COOKIE_NAME = 'testcookie'
     TEST_COOKIE_VALUE = 'worked'
+    MESSAGES_NAME = '_messages'
 
     def __init__(self, session_key=None):
         self._session_key = session_key
@@ -82,6 +83,20 @@
 
     def delete_test_cookie(self):
         del self[self.TEST_COOKIE_NAME]
+
+    def get_messages(self):
+            return self.get(self.MESSAGES_NAME, [])
+
+    def get_and_delete_messages(self):
+            return self.pop(self.MESSAGES_NAME, [])
+
+    def create_message(self, message):
+        messages = self.get(self.MESSAGES_NAME)
+        if messages is None:
+            messages = []
+            self[self.MESSAGES_NAME] = messages
+        messages.append(message)
+        self.modified = True
 
     def encode(self, session_dict):
         "Returns the given session dictionary pickled and encoded as a string."
diff --git a/django/contrib/sessions/tests.py b/django/contrib/sessions/tests.py
--- a/django/contrib/sessions/tests.py
+++ b/django/contrib/sessions/tests.py
@@ -18,6 +18,19 @@
 'dog'
 >>> db_session.pop('some key', 'does not exist')
 'does not exist'
+>>> db_session.get_messages()
+[]
+>>> db_session.create_message('first post')
+>>> db_session.get_messages()
+['first post']
+>>> db_session.get_and_delete_messages()
+['first post']
+>>> db_session.get_and_delete_messages()
+[]
+>>> db_session.create_message('hello')
+>>> db_session.create_message('world')
+>>> db_session.get_and_delete_messages()
+['hello', 'world']
 >>> db_session.save()
 >>> db_session.exists(db_session.session_key)
 True
@@ -69,6 +82,19 @@
 'dog'
 >>> file_session.pop('some key', 'does not exist')
 'does not exist'
+>>> file_session.get_messages()
+[]
+>>> file_session.create_message('first post')
+>>> file_session.get_messages()
+['first post']
+>>> file_session.get_and_delete_messages()
+['first post']
+>>> file_session.get_and_delete_messages()
+[]
+>>> file_session.create_message('hello')
+>>> file_session.create_message('world')
+>>> file_session.get_and_delete_messages()
+['hello', 'world']
 >>> file_session.save()
 >>> file_session.exists(file_session.session_key)
 True
@@ -131,6 +157,19 @@
 'dog'
 >>> cache_session.pop('some key', 'does not exist')
 'does not exist'
+>>> cache_session.get_messages()
+[]
+>>> cache_session.create_message('first post')
+>>> cache_session.get_messages()
+['first post']
+>>> cache_session.get_and_delete_messages()
+['first post']
+>>> cache_session.get_and_delete_messages()
+[]
+>>> cache_session.create_message('hello')
+>>> cache_session.create_message('world')
+>>> cache_session.get_and_delete_messages()
+['hello', 'world']
 >>> cache_session.save()
 >>> cache_session.delete(cache_session.session_key)
 >>> cache_session.exists(cache_session.session_key)
diff --git a/django/core/context_processors.py b/django/core/context_processors.py
--- a/django/core/context_processors.py
+++ b/django/core/context_processors.py
@@ -8,6 +8,46 @@
 """
 
 from django.conf import settings
+from django.utils.encoding import StrAndUnicode
+
+# LazyMessages is used by the `messages` and `auth` context processors.
+
+class LazyMessages(StrAndUnicode):
+    """
+    A lazy proxy for session and authentication messages.
+    """
+    def __init__(self, request):
+        self.request = request
+
+    def __iter__(self):
+        return iter(self.messages)
+
+    def __len__(self):
+        return len(self.messages)
+
+    def __nonzero__(self):
+        return bool(self.messages)
+
+    def __unicode__(self):
+        return unicode(self.messages)
+
+    def __getitem__(self, *args, **kwargs):
+        return self.messages.__getitem__(*args, **kwargs)
+
+    def _get_messages(self):
+        if hasattr(self, '_messages'):
+            return self._messages
+        # First, retrieve any messages for the user.
+        if hasattr(self.request, 'user') and \
+           hasattr(self.request.user, 'get_and_delete_messages'):
+            self._messages = self.request.user.get_and_delete_messages()
+        else:
+            self._messages = []
+        # Next, retrieve any messages for the session.
+        if hasattr(self.request, 'session'):
+            self._messages += self.request.session.get_and_delete_messages()
+        return self._messages
+    messages = property(_get_messages)
 
 def auth(request):
     """
@@ -22,11 +62,31 @@
     else:
         from django.contrib.auth.models import AnonymousUser
         user = AnonymousUser()
-    return {
+    context_extras = {
         'user': user,
-        'messages': user.get_and_delete_messages(),
         'perms': PermWrapper(user),
     }
+    # Add authentication (and session) LazyMessages to the context too.
+    context_extras.update(messages(request))
+    return context_extras
+
+def messages(request):
+    """
+    Returns messages for the session and the current user.
+
+    Note that this processor is only useful to use explicity if you are not
+    using the (enabled by default) auth processor, as it also provides the
+    messages (by calling this method).
+
+    The messages are lazy loaded, so no messages are retrieved and deleted
+    unless requested from the template.
+
+    Both contrib.session and contrib.auth are optional. If neither is provided,
+    no 'messages' variable will be added to the context.
+    """
+    if hasattr(request, 'session') or hasattr(request, 'user'):
+        return {'messages': LazyMessages(request)}
+    return {}
 
 def debug(request):
     "Returns context variables helpful for debugging."
diff --git a/docs/ref/templates/api.txt b/docs/ref/templates/api.txt
--- a/docs/ref/templates/api.txt
+++ b/docs/ref/templates/api.txt
@@ -352,11 +352,21 @@
       logged in).
 
     * ``messages`` -- A list of messages (as strings) for the currently
-      logged-in user. Behind the scenes, this calls
-      ``request.user.get_and_delete_messages()`` for every request. That method
-      collects the user's messages and deletes them from the database.
+      logged-in user.
 
-      Note that messages are set with ``user.message_set.create``.
+      .. versionadded:: 1.1
+
+      This ``messages`` list now also contains session messages.
+
+      The messages are not retrieved and cleared (using
+      ``get_and_delete_messages``) until the ``messages`` variable is accessed
+      in a template whereas previously, this context processor called
+      ``request.user.get_and_delete_messages()`` behind the scenes for every
+      request.
+
+      See the :ref:`authentication messages docs<auth-messages>` or
+      :ref:`session messages docs<sess-messages>` for information on creating
+      messages.
 
     * ``perms`` -- An instance of
       ``django.core.context_processors.PermWrapper``, representing the
@@ -404,6 +414,37 @@
 ``RequestContext`` will contain a variable ``request``, which is the current
 :class:`~django.http.HttpRequest`. Note that this processor is not enabled by default;
 you'll have to activate it.
+
+.. _messages-context-processor:
+
+django.core.context_processors.messages
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If :setting:`TEMPLATE_CONTEXT_PROCESSORS` contains this processor, every
+``RequestContext`` will contain a variable ``messages``, which is a list of
+messages (as strings) for the current session and the currently logged-in user.
+See the :ref:`session messages docs<sess-messages>` or the
+:ref:`authentication messages docs<auth-messages>` for more information on
+using messages.
+
+Note that this processor is only useful if you are not using the (enabled by
+default) ``auth`` processor, as it also provides the ``messages`` variable.
+
+The messages are not retrieved and cleared (using ``get_and_delete_messages``)
+until the ``messages`` variable is accessed in a template.
+
+Here's an example of template code that displays messages made available by this
+context processor:
+
+.. code-block:: html+django
+
+    {% if messages %}
+	<ul>
+	    {% for message in messages %}
+	    <li>{{ message }}</li>
+	    {% endfor %}
+	</ul>
+    {% endif %}
 
 Writing your own context processors
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/docs/topics/auth.txt b/docs/topics/auth.txt
--- a/docs/topics/auth.txt
+++ b/docs/topics/auth.txt
@@ -1151,10 +1151,13 @@
 access to a members-only portion of your site, or send them members-only e-mail
 messages.
 
+.. _auth-messages:
+
 Messages
 ========
 
-The message system is a lightweight way to queue messages for given users.
+The user message system is a lightweight way to queue messages for given users.
+To send messages to anonymous users, use :ref:`session messages<sess-messages>`.
 
 A message is associated with a :class:`~django.contrib.auth.models.User`.
 There's no concept of expiration or timestamps.
@@ -1186,24 +1189,18 @@
 
 When you use :class:`~django.template.context.RequestContext`, the currently
 logged-in user and his/her messages are made available in the
-:ref:`template context <ref-templates-api>` as the template variable
-``{{ messages }}``. Here's an example of template code that displays messages::
+:ref:`template context <ref-templates-api>` as the ``{{ messages }}`` template
+variable.
 
-    {% if messages %}
-    <ul>
-        {% for message in messages %}
-        <li>{{ message }}</li>
-        {% endfor %}
-    </ul>
-    {% endif %}
+.. versionadded:: 1.1
 
-Note that :class:`~django.template.context.RequestContext` calls
-:meth:`~django.contrib.auth.models.User.get_and_delete_messages` behind the
-scenes, so any messages will be deleted even if you don't display them.
+The ``{{ messages }}`` template variable will also contain session messages.
+For more information, see :ref:`messages-context-processor`
 
-Finally, note that this messages framework only works with users in the user
-database. To send messages to anonymous users, use the
-:ref:`session framework <topics-http-sessions>`.
+Also note that previously, ``RequestContext`` directly called
+``get_and_delete_messages`` behind the scenes, so any messages were deleted even
+if not displayed. Messages are now only deleted if the ``{{ messages }}``
+variable is accessed in a template.
 
 .. _authentication-backends:
 
diff --git a/docs/topics/http/sessions.txt b/docs/topics/http/sessions.txt
--- a/docs/topics/http/sessions.txt
+++ b/docs/topics/http/sessions.txt
@@ -266,6 +266,37 @@
         request.session.set_test_cookie()
         return render_to_response('foo/login_form.html')
 
+.. _sess-messages:
+
+Messages
+========
+
+.. versionadded:: 1.1
+
+The session message system provides a simple way to queue messages for all
+(anonymous or authenticated) site visitors. To associate messages with users in
+the user database, use the :ref:`authentication message framework<auth-messages>`.
+
+Messages are associated with a session, therefore a message only lasts as long
+as a session is valid (see `browser-length sessions vs. persistent sessions`_).
+
+The message system relies on the session middleware and is accessed via
+``request.session``. The API is simple:
+
+    * To create a new message, use
+      ``request.session.create_message(message='message text').``
+
+    * To retrieve the messages, use ``request.session.get_messages()``,
+      which returns a list of any messages (strings) in the session's queue.
+
+    * To retrieve and delete messages, use
+      ``request.session.get_and_delete_messages()``, which returns the list of
+      any messages in the session's queue and then deletes the messages from the
+      queue.
+
+The :ref:`messages-context-processor` context processor makes both session
+messages and user messages available to templates.
+
 Using sessions out of views
 ===========================
 
diff --git a/tests/regressiontests/messages/__init__.py b/tests/regressiontests/messages/__init__.py
new file mode 100644
--- /dev/null
+++ b/tests/regressiontests/messages/__init__.py
@@ -0,0 +1,1 @@
+
diff --git a/tests/regressiontests/messages/models.py b/tests/regressiontests/messages/models.py
new file mode 100644
diff --git a/tests/regressiontests/messages/tests.py b/tests/regressiontests/messages/tests.py
new file mode 100644
--- /dev/null
+++ b/tests/regressiontests/messages/tests.py
@@ -0,0 +1,77 @@
+"""
+>>> from django.core import context_processors
+>>> from django.http import HttpRequest
+
+Set up request with a fake user and session (just enough to test getting and
+deleting messages).
+>>> request = HttpRequest()
+>>> class FakeMessageObj:
+...     def __init__(self, object, messages):
+...         self.messages = messages
+...         self.object = object
+...     def get_and_delete_messages(self):
+...         print 'Getting and deleting any %s messages...' % self.object
+...         m = self.messages
+...         self.messages = []
+...         return m
+>>> request.user = FakeMessageObj('user', ['User message'])
+>>> request.session = FakeMessageObj('session', ['Message 1', 'Second message'])
+
+Run the messages context processor, and pull out the messages context variable.
+>>> context = context_processors.messages(request)
+>>> messages = context['messages']
+
+The messages context variable is a LazyMessages class. The messages haven't
+actually been retreived (and deleted) yet.
+>>> messages.__class__
+<class 'django.core.context_processors.LazyMessages'>
+
+When any of the following methods are called, the messages are retreived from
+the session (and user if contrib.auth is installed) from the LazyMessages
+object to be retreived: __iter__, __len__, __nonzero__, __unicode__,
+__getitem__
+>>> len(messages)
+Getting and deleting any user messages...
+Getting and deleting any session messages...
+3
+
+When messages are retreived, messages are deleted from the session (and user if
+contrib.auth is installed).
+>>> request.user.messages
+[]
+>>> request.session.messages
+[]
+
+The messages are still available to the LazyMessages instance because it caches
+them.
+>>> for message in messages:
+...     print message
+User message
+Message 1
+Second message
+>>> messages[-1]
+'Second message'
+
+Both contrib.sessions and contrib.auth are optional. If neither are provided,
+no 'messages' variable will be added to the context.
+>>> del request.user
+>>> request.session = FakeMessageObj('session', [])
+>>> context = context_processors.messages(request)
+>>> messages = context['messages']
+>>> if messages:
+...     print 'messages found!'
+Getting and deleting any session messages...
+
+>>> del request.session
+>>> request.user = FakeMessageObj('user', [])
+>>> context = context_processors.messages(request)
+>>> messages = context['messages']
+>>> if messages:
+...     print 'messages found!'
+Getting and deleting any user messages...
+
+>>> del request.user
+>>> context = context_processors.messages(request)
+>>> context
+{}
+"""
