• Get Review Board
  • What's New
  • Products
  • Review Board Code review, image review, and document review
  • Documentation
  • Release Notes
  • Power Pack Enterprise integrations, reports, and enhanced document review
  • Try for 60 Days
  • Purchase
  • RBCommons Review Board as a Service, hosted by us
  • Pricing
  • RBTools Command line tools and Python API for Review Board
  • Documentation
  • Release Notes
  • Review Bot Automated code review, connecting tools you already use
  • Documentation
  • Release Notes
  • RB Gateway Manage Git and Mercurial repositories in your network
  • Documentation
  • Release Notes
  • Learn and Explore
  • What is Code Review?
  • Documentation
  • Frequently Asked Questions
  • Support Options
  • Third-Party Integrations
  • Demo
  • Review Board RBTools Power Pack Review Bot Djblets RB Gateway
    1. Djblets 6.x
    2. Version 6.x
    3. Version 5.x
    4. Version 4.x
    5. Version 3.x
    6. Version 2.x
    7. Version 2.0
    8. Version 1.0
    9. Version 0.9
    10. Djblets Documentation
    11. Guides
    12. Caching Guides
    13. Caching Data
  • Home
  • Guides
  • Avatar Services Guides
  • Writing Avatar Services
  • Caching Guides
  • Caching Data
  • Working with Cache Keys
  • Cache Backends
  • Extension Guides
  • Writing Extensions
  • Testing Extensions
  • Feature Checks Guides
  • Introduction to Feature Checks
  • Writing Features
  • Writing Feature Checkers
  • Testing with Feature Checks
  • Integration Guides
  • Supporting Integrations
  • Writing Integrations
  • Dynamic Page Injections
  • Privacy Compliance Guides
  • Getting and Checking Consent
  • Working with Personally Identifiable Information
  • Service Integrations
  • Protection Guides
  • Rate Limiting Operations
  • reCAPTCHA Guides
  • Using reCAPTCHA
  • Registries Guides
  • Writing Registries
  • Web API Guides
  • Writing Web API Resources
  • Adding OAuth2 Support
  • Module and Class References
  • djblets
  • djblets.deprecation
  • djblets.auth.forms
  • djblets.auth.ratelimit
  • djblets.auth.signals
  • djblets.auth.util
  • djblets.auth.views
  • djblets.avatars.errors
  • djblets.avatars.forms
  • djblets.avatars.registry
  • djblets.avatars.services
  • djblets.avatars.services.base
  • djblets.avatars.services.fallback
  • djblets.avatars.services.file_upload
  • djblets.avatars.services.gravatar
  • djblets.avatars.services.url
  • djblets.avatars.settings
  • djblets.cache
  • djblets.cache.backend
  • djblets.cache.backend_compat
  • djblets.cache.context_processors
  • djblets.cache.errors
  • djblets.cache.forwarding_backend
  • djblets.cache.serials
  • djblets.cache.synchronizer
  • djblets.conditions
  • djblets.conditions.choices
  • djblets.conditions.conditions
  • djblets.conditions.errors
  • djblets.conditions.operators
  • djblets.conditions.values
  • djblets.configforms.forms
  • djblets.configforms.mixins
  • djblets.configforms.pages
  • djblets.configforms.registry
  • djblets.configforms.views
  • djblets.datagrid
  • djblets.datagrid.grids
  • djblets.db.backends.mysql.base
  • djblets.db.fields
  • djblets.db.fields.base64_field
  • djblets.db.fields.comma_separated_values_field
  • djblets.db.fields.counter_field
  • djblets.db.fields.json_field
  • djblets.db.fields.modification_timestamp_field
  • djblets.db.fields.relation_counter_field
  • djblets.db.managers
  • djblets.db.query
  • djblets.db.query_catcher
  • djblets.db.query_comparator
  • djblets.db.validators
  • djblets.pagestate
  • djblets.pagestate.injectors
  • djblets.pagestate.middleware
  • djblets.pagestate.state
  • djblets.pagestate.templatetags.djblets_pagestate
  • djblets.extensions
  • djblets.extensions.admin
  • djblets.extensions.errors
  • djblets.extensions.extension
  • djblets.extensions.forms
  • djblets.extensions.hooks
  • djblets.extensions.loaders
  • djblets.extensions.manager
  • djblets.extensions.middleware
  • djblets.extensions.models
  • djblets.extensions.packaging
  • djblets.extensions.resources
  • djblets.extensions.settings
  • djblets.extensions.signals
  • djblets.extensions.staticfiles
  • djblets.extensions.testing
  • djblets.extensions.testing.testcases
  • djblets.extensions.urls
  • djblets.extensions.views
  • djblets.extensions.templatetags.djblets_extensions
  • djblets.features
  • djblets.features.checkers
  • djblets.features.decorators
  • djblets.features.errors
  • djblets.features.feature
  • djblets.features.level
  • djblets.features.registry
  • djblets.features.testing
  • djblets.features.templatetags.features
  • djblets.forms.fields
  • djblets.forms.fieldsets
  • djblets.forms.forms
  • djblets.forms.forms.key_value_form
  • djblets.forms.widgets
  • djblets.gravatars
  • djblets.gravatars.templatetags.gravatars
  • djblets.http.middleware
  • djblets.http.requests
  • djblets.http.responses
  • djblets.integrations.errors
  • djblets.integrations.forms
  • djblets.integrations.hooks
  • djblets.integrations.integration
  • djblets.integrations.manager
  • djblets.integrations.mixins
  • djblets.integrations.models
  • djblets.integrations.urls
  • djblets.integrations.views
  • djblets.log
  • djblets.log.middleware
  • djblets.log.siteconfig
  • djblets.log.urls
  • djblets.log.views
  • djblets.mail.dmarc
  • djblets.mail.message
  • djblets.mail.testing
  • djblets.mail.utils
  • djblets.markdown
  • djblets.markdown.extensions.escape_html
  • djblets.markdown.extensions.wysiwyg
  • djblets.markdown.extensions.wysiwyg_email
  • djblets.pipeline.compilers.es6
  • djblets.pipeline.compilers.less
  • djblets.pipeline.compilers.mixins
  • djblets.pipeline.compilers.rollup
  • djblets.pipeline.compilers.typescript
  • djblets.pipeline.settings
  • djblets.privacy.consent
  • djblets.privacy.consent.base
  • djblets.privacy.consent.common
  • djblets.privacy.consent.errors
  • djblets.privacy.consent.forms
  • djblets.privacy.consent.hooks
  • djblets.privacy.consent.registry
  • djblets.privacy.consent.tracker
  • djblets.privacy.models
  • djblets.privacy.pii
  • djblets.privacy.templatetags.djblets_privacy
  • djblets.protect
  • djblets.protect.locks
  • djblets.protect.ratelimit
  • djblets.recaptcha.mixins
  • djblets.recaptcha.siteconfig
  • djblets.recaptcha.templatetags.djblets_recaptcha
  • djblets.recaptcha.widgets
  • djblets.registries
  • djblets.registries.errors
  • djblets.registries.importer
  • djblets.registries.mixins
  • djblets.registries.registry
  • djblets.registries.signals
  • djblets.secrets
  • djblets.secrets.crypto
  • djblets.secrets.token_generators
  • djblets.secrets.token_generators.base
  • djblets.secrets.token_generators.legacy_sha1
  • djblets.secrets.token_generators.registry
  • djblets.secrets.token_generators.vendor_checksum
  • djblets.siteconfig
  • djblets.siteconfig.admin
  • djblets.siteconfig.context_processors
  • djblets.siteconfig.django_settings
  • djblets.siteconfig.forms
  • djblets.siteconfig.managers
  • djblets.siteconfig.middleware
  • djblets.siteconfig.models
  • djblets.siteconfig.signals
  • djblets.siteconfig.views
  • djblets.template.caches
  • djblets.template.context
  • djblets.template.loaders.conditional_cached
  • djblets.template.loaders.namespaced_app_dirs
  • djblets.testing.decorators
  • djblets.testing.testcases
  • djblets.testing.testrunners
  • djblets.urls.context_processors
  • djblets.urls.decorators
  • djblets.urls.patterns
  • djblets.urls.resolvers
  • djblets.urls.root
  • djblets.urls.staticfiles
  • djblets.util.compat.django.core.cache
  • djblets.util.compat.python.past
  • djblets.util.contextmanagers
  • djblets.util.dates
  • djblets.util.decorators
  • djblets.util.filesystem
  • djblets.util.functional
  • djblets.util.html
  • djblets.util.http
  • djblets.util.humanize
  • djblets.util.json_utils
  • djblets.util.properties
  • djblets.util.serializers
  • djblets.util.symbols
  • djblets.util.templatetags.djblets_deco
  • djblets.util.templatetags.djblets_email
  • djblets.util.templatetags.djblets_forms
  • djblets.util.templatetags.djblets_images
  • djblets.util.templatetags.djblets_js
  • djblets.util.templatetags.djblets_utils
  • djblets.util.typing
  • djblets.util.views
  • djblets.views.generic.base
  • djblets.views.generic.etag
  • djblets.webapi.auth
  • djblets.webapi.auth.backends
  • djblets.webapi.auth.backends.api_tokens
  • djblets.webapi.auth.backends.base
  • djblets.webapi.auth.backends.basic
  • djblets.webapi.auth.backends.oauth2_tokens
  • djblets.webapi.auth.views
  • djblets.webapi.decorators
  • djblets.webapi.encoders
  • djblets.webapi.errors
  • djblets.webapi.fields
  • djblets.webapi.managers
  • djblets.webapi.models
  • djblets.webapi.oauth2_scopes
  • djblets.webapi.resources
  • djblets.webapi.resources.base
  • djblets.webapi.resources.group
  • djblets.webapi.resources.registry
  • djblets.webapi.resources.root
  • djblets.webapi.resources.user
  • djblets.webapi.resources.mixins.api_tokens
  • djblets.webapi.resources.mixins.forms
  • djblets.webapi.resources.mixins.oauth2_tokens
  • djblets.webapi.resources.mixins.queries
  • djblets.webapi.responses
  • djblets.webapi.signals
  • djblets.webapi.testing
  • djblets.webapi.testing.decorators
  • djblets.webapi.testing.testcases
  • General Index
  • Python Module Index
  • Release Notes
  • Caching Data¶

    Djblets provides a pair of utility functions on top of Django’s cache framework for storing computed values and large datasets:

    • cache_memoize()

    • cache_memoize_iter()

    These build upon what’s provided in Django to help handle a variety of cache needs in more advanced applications, covering:

    • Key normalization (including namespacing across Django sites, protection against unsafe input, and workarounds for cache key size constraints)

    • Chunking and compression of large data

    • Storage and retrieval of iterable sets of data

    • Optional encryption of cache keys and data

    • Optional locking of cache operations across processes/servers

    Caching a Single Value¶

    cache_memoize() takes a pre-normalized cache key and a function that generates the data to store.

    If the key already exists in cache, it will return the value as-is. Otherwise it’ll call the function, take the result, and store it in cache.

    from djblets.cache.backend import cache_memoize
    
    
    def get_expensive_value() -> str:
        return cache_memoize(
            'my-expensive-value',
            lambda: some_slow_computation(),
        )
    

    The function argument can be any zero-argument callable, including a plain lambda, a bound method, or functools.partial().

    By default, values are cached for 30 days. This can be changed per-call with expiration:

    result = cache_memoize(
        'my-value',
        compute_value_func,
        expiration=60 * 60,  # 1 hour
    )
    

    The global default expiration can also be changed by setting CACHE_EXPIRATION_TIME to a number of seconds.

    Caching Iterables and Generators¶

    cache_memoize_iter() is designed for caching the output of a generator or any iterable. It always stores data in chunked form, making it well suited for large result sets.

    This function takes all the same options that cache_memoize() does, allowing for key normalization, encryption, compression, and more.

    The second argument can be an iterable (list, queryset, generator) or a callable that returns one:

    from typing import Iterator
    
    from djblets.cache.backend import cache_memoize_iter
    
    
    def get_all_items() -> Iterator[Item]:
        return cache_memoize_iter(
            'all-items',
            lambda: Item.objects.all(),
        )
    

    The return value is always a generator.

    Important

    Always consume the generator completely, or later data from the generator won’t be stored in the cache. This will lead to corruption when next retrieving the data.

    If the callable itself is a generator function, items are yielded to the caller as they are produced, and cached in the background:

    def fetch_items_generator() -> Iterator[Item]:
        ...
    
    
    def process_items() -> None:
        for item in cache_memoize_iter('all-items', fetch_items_generator):
            handle(item)
    

    Caching Capabilities¶

    Both cache_memoize() and cache_memoize_iter() provide a number of capabilities to control how data is cached.

    Force-Refreshing a Value¶

    To bypass the cache and always recompute a fresh value, pass force_overwrite=True. The result will be stored over any existing cached entry:

    result = cache_memoize(
        'my-key',
        compute_value_func,
        force_overwrite=True,
    )
    
    result = cache_memoize_iter(
        'my-iter-key',
        compute_value_iter,
        force_overwrite=True,
    )
    

    Storing Large Data¶

    Django’s default cache backends (including memcached) have a per-entry size limit of around 1MB. This can cause failures when trying to cache large data.

    When storing data that may be larger than this, pass large_data=True to cache_memoize() (this is always enabled for cache_memoize_iter()).

    Djblets will serialize and compress the value and automatically split it across as multiple cache entries:

    result = cache_memoize(
        'big-report',
        build_report,
        large_data=True,
    )
    

    Compression is enabled by default and can be turned off using compress_large_data=False, though this is rarely useful since compression typically reduces both cache consumption and retrieval time for large data.

    Coordinating Writes with a Cache Lock¶

    New in version 5.3.

    In multi-process or multi-threaded deployments, multiple workers may simultaneously detect a cache miss and attempt to recompute the same value.

    Passing a CacheLock prevents this stampede by letting only the first worker compute and populate the value while others wait and then read the freshly cached result:

    from djblets.cache.backend import cache_memoize
    from djblets.protect.locks import CacheLock
    
    
    result = cache_memoize(
        'my-key',
        compute_value_func,
        lock=CacheLock('my-key-lock'),
    )
    
    result = cache_memoize_iter(
        'my-iter-key',
        compute_value_iter,
        lock=CacheLock('my-iter-key-lock'),
    )
    

    Note

    This is a soft lock, which makes a best-attempt at locking. It uses the cache backend to manage the lock, which memcached is not designed for.

    Because of this, there is still a possibility that under heavy load, multiple processes/servers may end up computing and caching the same state at the same time. Even in this case, most callers will still wait for the lock to be released, and will then retrieve the cached value.

    Encrypting Cached Keys and Values¶

    New in version 3.0.

    Both functions support optional AES encryption of stored keys and values. This is useful when the cache may be shared between services or when the cached data is sensitive.

    To enable encryption for a specific call, pass use_encryption=True:

    result = cache_memoize(
        'my-key',
        fetch_sensitive_data,
        use_encryption=True,
    )
    
    result = cache_memoize_iter(
        'my-iter-key',
        fetch_sensitive_data_iter,
        use_encryption=True,
    )
    

    Neither the cache key nor the data will be readable or guessable without access to the encryption key.

    The default encryption key comes from DJBLETS_CACHE_DEFAULT_ENCRYPTION_KEY if set, and otherwise falls back to the server’s default AES key (see get_default_aes_encryption_key()).

    You can also supply an explicit key:

    result = cache_memoize(
        'my-key',
        fetch_sensitive_data,
        use_encryption=True,
        encryption_key=b'my-32-byte-aes-key-here.........',
    )
    
    result = cache_memoize_iter(
        'my-iter-key',
        fetch_sensitive_data_iter,
        use_encryption=True,
        encryption_key=b'my-32-byte-aes-key-here.........',
    )
    

    To enforce encryption for all cache operations across the entire application, set DJBLETS_CACHE_FORCE_ENCRYPTION to True. No per-call changes are needed.

    Keep up with the latest Review Board releases, security updates, and helpful information.

    About
    News
    Demo
    RBCommons Hosting
    Integrations
    Happy Users
    Support Options
    Documentation
    FAQ
    User Manual
    RBTools
    Administration Guide
    Power Pack
    Release Notes
    Downloads
    Review Board
    RBTools
    Djblets
    Power Pack
    Package Store
    PGP Signatures
    Contributing
    Bug Tracker
    Submit Patches
    Development Setup
    Wiki
    Follow Us
    Mailing Lists
    Reddit
    Twitter
    Mastodon
    Facebook
    YouTube
    Copyright © 2006-2026 Beanbag, Inc. All rights reserved.
    Terms of Service — Privacy Policy — AI Ethics Policy — Branding

    On this page

    • [Top]
    • Caching a Single Value
    • Caching Iterables and Generators
    • Caching Capabilities
      • Force-Refreshing a Value
      • Storing Large Data
      • Coordinating Writes with a Cache Lock
      • Encrypting Cached Keys and Values