# Django Database Cache - Untouched expired entries are never culled unless MAX\_ENTRIES is reached

**URL:** <https://forum.djangoproject.com/t/django-database-cache-untouched-expired-entries-are-never-culled-unless-max-entries-is-reached/22679>\
**Category:** Forms & APIs\
**Created:** [July 31, 2023, 10:25am UTC](https://forum.djangoproject.com/t/django-database-cache-untouched-expired-entries-are-never-culled-unless-max-entries-is-reached/22679 "2023-07-31T10:25:38Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![KonstantinSchubert](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/konstantinschubert/32/15083_2.png) [@KonstantinSchubert](https://forum.djangoproject.com/u/KonstantinSchubert)\
**Post date:** [July 31, 2023, 10:25am UTC](https://forum.djangoproject.com/t/django-database-cache-untouched-expired-entries-are-never-culled-unless-max-entries-is-reached/22679/1 "2023-07-31T10:25:38Z")

</div>

The documentation for the Django database backend says:

```auto
Unlike other cache backends, the database cache does not support 
automatic culling of expired entries at the database level.
 Instead, expired cache entries are culled each time 
add(), set(), or touch() is called.

```

But this doesn’t seem to be what is happening:

In fact, expired entries are only deleted if MAX\_ENTRIES is reached: [https://github.com/django/django/blob/main/django/core/cache/backends/db.py#L130](https://github.com/django/django/blob/main/django/core/cache/backends/db.py#L130)

But this then also triggers culling of non-expired entries if their number exceeds MAX\_ENTRIES.

This is a problem if I want to drive a strategy where I only expire entries by time and never randomly cull them. In order to prevent random culling, I need to set MAX\_ENTRIES to a very high unreachable number. But then, expired entries will never be deleted!

Am I maybe missing something? Or is the documentation incomplete here?  
Is it a possible consideration to update the database caching backend to cull expired entries also when MAX\_ENTRIES isn’t reached yet?

PS: The documentation also doesn’t mention that expired entries are removed if you try to `get` them: [https://github.com/django/django/blob/main/django/core/cache/backends/db.py#L97](https://github.com/django/django/blob/main/django/core/cache/backends/db.py#L97)

---

<div class="post-metadata">

**Author:** ![eschdeuse](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/eschdeuse/32/26849_2.png) [@eschdeuse](https://forum.djangoproject.com/u/eschdeuse)\
**Post date:** [February 11, 2025, 8:53am UTC](https://forum.djangoproject.com/t/django-database-cache-untouched-expired-entries-are-never-culled-unless-max-entries-is-reached/22679/2 "2025-02-11T08:53:22Z")

</div>

Hello, any news regarding this ? What did you do eventually ?

---

<div class="post-metadata">

**Author:** ![jacobtylerwalls](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/jacobtylerwalls/32/30603_2.png) [@jacobtylerwalls](https://forum.djangoproject.com/u/jacobtylerwalls)\
**Post date:** [May 29, 2026, 4:27pm UTC](https://forum.djangoproject.com/t/django-database-cache-untouched-expired-entries-are-never-culled-unless-max-entries-is-reached/22679/3 "2026-05-29T16:27:57Z")

</div>

Thanks for this, I opened a [ticket](https://code.djangoproject.com/ticket/37129) for the first infelicity in the documentation re: the interaction with MAX\_ENTRIES.

> In order to prevent random culling, I need to set MAX\_ENTRIES to a very high unreachable number. But then, expired entries will never be deleted!

You should be able to set `CULL_FREQUENCY` to a very high, unreachable number, and set `MAX_ENTRIES` to 0.

We should probably optimize this use case to remove the unnecessary SELECT that would occur in this scenario (if `cull_num` in the implementation is 0, we already know we can exit without doing a SELECT that we’d otherwise need for a `SELECT`/`DELETE` pair).

I opened a [ticket](https://code.djangoproject.com/ticket/37130) for that, too.
