[Django] #27641: Default CACHES uses Locmem which isn't suitable for production

82 views
Skip to first unread message

Django

unread,
Dec 26, 2016, 12:43:12 PM12/26/16
to django-...@googlegroups.com
#27641: Default CACHES uses Locmem which isn't suitable for production
-------------------------------------+-------------------------------------
Reporter: Adam | Owner: Adam Chainz
Chainz |
Type: | Status: assigned
Cleanup/optimization |
Component: Core | Version: 1.10
(Cache system) |
Severity: Normal | Keywords:
Triage Stage: | Has patch: 0
Unreviewed |
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-------------------------------------+-------------------------------------
The default CACHES that Django uses is defined in `global_settings` as:

{{{
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
}
}
}}}

Django also enforces that you have a cache called 'default' defined:
https://docs.djangoproject.com/en/1.10/ref/checks/#caches

`LocMemCache` only works within a single process and thus is not suitable
for even the smallest application deployments these days, which nearly
always use multiple web worker processes under uWSGI/gunicorn. (For
example, [https://github.com/unbit/uwsgi-
docs/blob/master/tutorials/heroku_python.rst this uWSGI Heroku tutorial]
has config for 4 processes).

The way Django uses caching is to assume there's a single cache for the
whole application which could lead code to break in unexpected ways in
production.

I'd like to suggest either:

1. A deployment check that the cache used in production is not locmemcache
2. The default cache backend used in `global_settings` be changed to
`DummyCache`

Since (2) is probably highly backwards incompatible, I think (1) is
preferable.

--
Ticket URL: <https://code.djangoproject.com/ticket/27641>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Dec 26, 2016, 12:43:23 PM12/26/16
to django-...@googlegroups.com
#27641: Default CACHES uses Locmem which isn't suitable for production
-------------------------------------+-------------------------------------
Reporter: Adam Chainz | Owner: Adam
Type: | Chainz
Cleanup/optimization | Status: assigned
Component: Core (Cache system) | Version: 1.10
Severity: Normal | Resolution:
Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Adam Chainz):

* cc: me@… (added)


--
Ticket URL: <https://code.djangoproject.com/ticket/27641#comment:1>

Django

unread,
Dec 26, 2016, 7:49:47 PM12/26/16
to django-...@googlegroups.com
#27641: Default CACHES uses Locmem which isn't suitable for production
-------------------------------------+-------------------------------------
Reporter: Adam Chainz | Owner: Adam
Type: | Chainz
Cleanup/optimization | Status: assigned
Component: Core (Cache system) | Version: 1.10
Severity: Normal | Resolution:
Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Tim Graham):

I'm not sure about adding a system check which would require simple sites
to silence that check if they don't care about caching. Maybe you can
write to the DevelopersMailingList to get some other opinions. I think it
might be enough to enhance the
[https://docs.djangoproject.com/en/stable/howto/deployment/checklist/
deployment checklist] with a note about this issue.

--
Ticket URL: <https://code.djangoproject.com/ticket/27641#comment:2>

Django

unread,
Dec 27, 2016, 5:06:54 AM12/27/16
to django-...@googlegroups.com
#27641: Default CACHES uses Locmem which isn't suitable for production
-------------------------------------+-------------------------------------
Reporter: Adam Chainz | Owner: Adam
Type: | Chainz
Cleanup/optimization | Status: assigned
Component: Core (Cache system) | Version: 1.10
Severity: Normal | Resolution:
Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Claude Paroz):

I do agree with Tim. I'm deploying many small single-process apps using
Apache/mod_wsgi and I *think* using locmem cache is fine (even if I'm
using memcache in several of these instances).

--
Ticket URL: <https://code.djangoproject.com/ticket/27641#comment:3>

Django

unread,
Dec 27, 2016, 5:22:34 AM12/27/16
to django-...@googlegroups.com
#27641: Default CACHES uses Locmem which isn't suitable for production
-------------------------------------+-------------------------------------
Reporter: Adam Chainz | Owner: Adam
Type: | Chainz
Cleanup/optimization | Status: assigned
Component: Core (Cache system) | Version: 1.10
Severity: Normal | Resolution:
Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Aymeric Augustin):

> The way Django uses caching is to assume there's a single cache for the
whole application

This is correct, hovewer, considering the contract of Django cache
backends -- keys can be evicted arbitrarily -- I believe that in (most)
(reasonable) cases the effect of separate workers using separate caches is
lower performance (cache hits / N for N workers) and increased resource
usage (memory * N for N workers). This is annoying but not always worth
the effort of setting up or paying for a separate cache server. I have
used the locmem cache successfully in production for modest optimizations
such as template caching.

I'd rather handle this in the documentation.

One surprising and little know characteristic of the locmem cache backend
is that it's bounded to 300 keys by default. Even for caching medium-size
objects (let's say 8kB), that's quite low (limited to 2,4MB). I'm not sure
the docs mention it sufficiently clearly. If we explain the downsides of
using the locmem cache in production, it would be a good place to mention
that this setting likely needs tuning.

--
Ticket URL: <https://code.djangoproject.com/ticket/27641#comment:4>

Django

unread,
Dec 27, 2016, 8:39:13 AM12/27/16
to django-...@googlegroups.com
#27641: Document limitations of the Locmem cache backend

-------------------------------------+-------------------------------------
Reporter: Adam Chainz | Owner: Adam
Type: | Chainz
Cleanup/optimization | Status: assigned
Component: Documentation | Version: 1.10
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Tim Graham):

* component: Core (Cache system) => Documentation
* stage: Unreviewed => Accepted


Comment:

Some limitations are already documented in
[https://docs.djangoproject.com/en/stable/topics/cache/#local-memory-
caching Local-memory caching].

--
Ticket URL: <https://code.djangoproject.com/ticket/27641#comment:5>

Django

unread,
Dec 28, 2016, 3:55:22 PM12/28/16
to django-...@googlegroups.com
#27641: Document limitations of the Locmem cache backend
-------------------------------------+-------------------------------------
Reporter: Adam Chainz | Owner: Adam
Type: | Chainz
Cleanup/optimization | Status: assigned
Component: Documentation | Version: 1.10
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Adam Chainz):

considering the contract of Django cache backends -- keys can be evicted
arbitrarily

The contract of `cache.delete()` though is that the value is gone, but it
can't be with per-process caches - that's the main confusion I'm worried
about.

Actually thanks for linking Tim, the docs do already say quite a lot. The
last paragraph makes it obvious that it's probably not suitable:

Note that each process will have its own private cache instance, which
means no cross-process caching is possible. This obviously also means the
local memory cache isn’t particularly memory-efficient, so it’s probably
not a good choice for production environments. It’s nice for development.

My main concern is for projects that don't realize they're using caching
and thus don't read the caching docs, that's why I suggested a deploy
check since it's unavoidable. I think it would be best to include a bit
more under the the
[https://docs.djangoproject.com/en/1.10/howto/deployment/checklist/#caches
`CACHES` section in the deployment checklist], and also a sentence about
the low default size on the caching page.

--
Ticket URL: <https://code.djangoproject.com/ticket/27641#comment:6>

Django

unread,
Dec 28, 2016, 3:58:54 PM12/28/16
to django-...@googlegroups.com
#27641: Document limitations of the Locmem cache backend
-------------------------------------+-------------------------------------
Reporter: Adam Chainz | Owner: Adam
Type: | Chainz
Cleanup/optimization | Status: assigned
Component: Documentation | Version: 1.10
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Aymeric Augustin):

Yes, while my argument seems correct for a single requests, separate
caches could create incorrect results for sequences of requests.

Adding a link from the deployment checklist to the paragraph that
describes the limitations sounds like a good idea.

--
Ticket URL: <https://code.djangoproject.com/ticket/27641#comment:7>

Django

unread,
Dec 28, 2016, 5:30:17 PM12/28/16
to django-...@googlegroups.com
#27641: Document limitations of the Locmem cache backend
-------------------------------------+-------------------------------------
Reporter: Adam Chainz | Owner: Adam
Type: | Chainz
Cleanup/optimization | Status: assigned
Component: Documentation | Version: 1.10
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Tim Graham):

* has_patch: 0 => 1


Comment:

[https://github.com/django/django/pull/7757 PR] from Adam.

--
Ticket URL: <https://code.djangoproject.com/ticket/27641#comment:8>

Django

unread,
Dec 28, 2016, 7:43:36 PM12/28/16
to django-...@googlegroups.com
#27641: Document limitations of the Locmem cache backend
-------------------------------------+-------------------------------------
Reporter: Adam Chainz | Owner: Adam
Type: | Chainz
Cleanup/optimization | Status: closed
Component: Documentation | Version: 1.10
Severity: Normal | Resolution: fixed
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Tim Graham <timograham@…>):

* status: assigned => closed
* resolution: => fixed


Comment:

In [changeset:"755406f5ff888e91bacb26f63cbddf7c036793ca" 755406f]:
{{{
#!CommitTicketReference repository=""
revision="755406f5ff888e91bacb26f63cbddf7c036793ca"
Fixed #27641 -- Doc'd default local-memory caching in deployment
checklist.
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/27641#comment:9>

Django

unread,
Dec 28, 2016, 7:43:52 PM12/28/16
to django-...@googlegroups.com
#27641: Document limitations of the Locmem cache backend
-------------------------------------+-------------------------------------
Reporter: Adam Chainz | Owner: Adam
Type: | Chainz
Cleanup/optimization | Status: closed
Component: Documentation | Version: 1.10
Severity: Normal | Resolution: fixed
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Tim Graham <timograham@…>):

In [changeset:"f5e0e15ef893a6cca69dbea2da043cc751b60739" f5e0e15e]:
{{{
#!CommitTicketReference repository=""
revision="f5e0e15ef893a6cca69dbea2da043cc751b60739"
[1.10.x] Fixed #27641 -- Doc'd default local-memory caching in deployment
checklist.

Backport of 755406f5ff888e91bacb26f63cbddf7c036793ca from master
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/27641#comment:10>

Reply all
Reply to author
Forward
0 new messages