Claude Skill

bitrix-caching

Covers caching in Bitrix — Cache (unmanaged), ManagedCache, TaggedCache, ORM auto-cache, component cache via startResultCache/endResultCache, Composite Site, cache engine configuration (files, memcached, redis) in .settings.php. Applied when optimizing performance, invalidating b

LLM Mart · 0 points · 12 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download bxmaximum-bitrix-framework-skills-skills_bitrix-caching-66c40e0.zip · 3 KB
Part of bxmaximum/bitrix-framework-skills — 38 skills

Install

skills CLI npx skills add https://github.com/bxmaximum/bitrix-framework-skills/tree/main/skills/bitrix-caching
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install bxmaximum-bitrix-framework-skills@llmmart
Git git clone https://github.com/bxmaximum/bitrix-framework-skills.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole bxmaximum/bitrix-framework-skills collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

Caching in Bitrix

Cache Levels

  1. Unmanaged Cache (Bitrix\Main\Data\Cache) — with TTL, key, and path. Cleared automatically by TTL and manually.
  2. Managed Cache (ManagedCache) — lives until explicit invalidation, convenient for "rarely changing" data.
  3. Tagged Cache (TaggedCache) — keys are grouped by tags; invalidating one tag clears all associated entries.
  4. ORM Cache — automatic: isCacheable() in the tablet + ['cache' => ['ttl' => ...]] in getList.
  5. Component Cache — via startResultCache() / endResultCache() and parameters CACHE_TYPE, CACHE_TIME, CACHE_GROUPS.
  6. Composite Cache — HTML cache of the entire page (Bitrix\Main\Composite\Engine).

Configuration in .settings.php

'cache' => [
    'value' => [
        'type' => [
            // 'class_name' => \Bitrix\Main\Data\CacheEngineRedis::class, // one of these
            'type' => 'redis',     // files|memcache|redis|apc|xcache|none
            'host' => '127.0.0.1',
            'port' => 6379,
            'serializer' => \Redis::SERIALIZER_IGBINARY,
        ],
        'sid' => 'PROJECT_',       // key prefix
        'cache_flags' => [
            'config_options' => 3600,
            'site_template' => 3600,
            'iblock_include' => 3600,
        ],
    ],
    'readonly' => false,
],

Different sections (config_options, menu, site_template, etc.) define TTL for internal kernel caches.

Unmanaged Cache Template

$cache = \Bitrix\Main\Data\Cache::createInstance();
$ttl = 3600;
$cacheId = 'posts_list_' . md5(serialize($filter));
$cacheDir = '/vendor_blog/posts';

if ($cache->initCache($ttl, $cacheId, $cacheDir))
{
    $data = $cache->getVars();
}
elseif ($cache->startDataCache())
{
    $data = PostTable::getList([
        'filter' => $filter,
        'select' => ['ID', 'TITLE'],
    ])->fetchAll();

    // If conditions are not met — stop writing cache:
    if (empty($data))
    {
        $cache->abortDataCache();
    }
    else
    {
        $cache->endDataCache($data);
    }
}
  • cacheId — unique key, includes all variables affecting the result.
  • cacheDir — cache "folder"; convenient to clear by directory $cache->cleanDir($cacheDir).

Managed Cache

$managed = \Bitrix\Main\Application::getInstance()->getManagedCache();

if ($managed->read(86400, $cacheId, 'posts'))
{
    $data = $managed->get($cacheId);
}
else
{
    $data = $this->fetchExpensive();
    $managed->setImmediate($cacheId, $data); // or set() — write at the end of request
}

// Invalidation:
$managed->clean($cacheId, 'posts');
$managed->cleanDir('posts');

Tags

use Bitrix\Main\Application;

$taggedCache = Application::getInstance()->getTaggedCache();

$taggedCache->startTagCache('/vendor_blog/posts');
$taggedCache->registerTag('posts_list');
$taggedCache->registerTag('post_42');
$taggedCache->endTagCache();

// Tag invalidation — clears all entries registered under this tag:
$taggedCache->clearByTag('posts_list');

Use your own tag names for HTML/component caches. There are no automatic TaggedCache tags like ORM_<TABLE_NAME>.

ORM Query Cache

PostTable::getList([
    'select' => ['*'],
    'filter' => ['=ACTIVE' => 'Y'],
    'cache'  => [
        'ttl' => 3600,
        'cache_joins' => true, // cache JOIN queries
    ],
]);

ORM auto-cache is stored under ManagedCache directories orm_<table_name> (see Entity::getCacheDir()). Invalidate via:

PostTable::cleanCache();           // DataManager / Table
PostTable::getEntity()->cleanCache(); // Entity — ManagedCache::cleanDir('orm_...')

Writes that change cacheable rows also call cleanCache() from the ORM layer. To clear related TaggedCache HTML, register and invalidate your own tags in event handlers — do not invent ORM_* tag names.

Component Cache

In class.php / component.php:

if ($this->startResultCache(false, [
    $USER->IsAuthorized(),
    $arParams['SECTION_ID'],
]))
{
    $this->arResult['ITEMS'] = $this->fetchItems();
    $this->includeComponentTemplate();
}

Component parameters controlling cache:

  • CACHE_TYPE: A (autocache), Y, N.
  • CACHE_TIME: TTL in seconds.
  • CACHE_GROUPS: Y — key depends on user groups.

Composite Cache

Enable and configure Composite Site in Admin → Settings → Composite Site (or programmatically via Bitrix\Main\Composite\Engine). There is no separate "compression module" requirement for composite.

Consider composite constraints: dynamic blocks are marked via $APPLICATION->SetPageProperty('composite_frame_mode', 'Y') / setFrameMode, personal data should not be in the static part, AJAX components are fetched with a separate request.

Composite zones and NGINX

  • Static zone — full page HTML cache.
  • Dynamic zone (data-dynamic) — refreshed via AJAX on each hit.
  • Autocomposite vs manual composite — configure in Admin → Composite settings.
  • NGINX can serve static composite files directly; configure composite pool path (BitrixVM: Configure nginx to use composite cache).

For ORM/SQL optimization see skill bitrix-performance.

Invalidation by Events

Typical scheme: OnAfterUpdate/OnAfter* handler in the tablet calls $taggedCache->clearByTag(...) for your tags, and/or Table::cleanCache() for ORM query cache. Use new ORM events via EventResult instead of $GLOBALS['USER_FIELD_MANAGER']->....

Antipatterns

  • Caching "live" data (balances, stock levels) with high TTL without invalidation.
  • Using global $_SESSION/$USER inside the cache key instead of explicit variables.
  • One shared cacheDir for all modules — hard to clear selectively.
  • Missing abortDataCache() for empty/error results.
  • Enabling composite without testing dynamic blocks.
  • Assuming TaggedCache tags ORM_<TABLE> exist — use cleanCache() / orm_* ManagedCache dirs instead.

Checklist

  • Cache level selected: short-lived → unmanaged; rarely changing and critical → managed + tags.
  • Cache key includes all parameters affecting the result (filters, language, permissions).
  • Cache invalidation is automated via tags/events, not manual cleanDir('/').
  • ORM query cache cleared via Table::cleanCache() / Entity::cleanCache(), not fictional ORM_* tags.
  • Component cache accounts for user groups where important.
  • Production environment uses Redis/Memcached instead of file cache.
Files (bitrix-framework-skills)
  • SKILL.md 6.8 KB
    ---
    name: bitrix-caching
    description: Covers caching in Bitrix — Cache (unmanaged), ManagedCache, TaggedCache, ORM auto-cache, component cache via startResultCache/endResultCache, Composite Site, cache engine configuration (files, memcached, redis) in .settings.php. Applied when optimizing performance, invalidating by tags and events, setting TTL, cache warm-up, and debugging cache hits. Key terms — cache, invalidate, TaggedCache, ManagedCache, startResultCache, cacheDir, clean.
    ---
    
    # Caching in Bitrix
    
    ## Cache Levels
    
    1. **Unmanaged Cache** (`Bitrix\Main\Data\Cache`) — with TTL, key, and path. Cleared automatically by TTL and manually.
    2. **Managed Cache** (`ManagedCache`) — lives until explicit invalidation, convenient for "rarely changing" data.
    3. **Tagged Cache** (`TaggedCache`) — keys are grouped by tags; invalidating one tag clears all associated entries.
    4. **ORM Cache** — automatic: `isCacheable()` in the tablet + `['cache' => ['ttl' => ...]]` in `getList`.
    5. **Component Cache** — via `startResultCache()` / `endResultCache()` and parameters `CACHE_TYPE`, `CACHE_TIME`, `CACHE_GROUPS`.
    6. **Composite Cache** — HTML cache of the entire page (`Bitrix\Main\Composite\Engine`).
    
    ## Configuration in `.settings.php`
    
    ```php
    'cache' => [
        'value' => [
            'type' => [
                // 'class_name' => \Bitrix\Main\Data\CacheEngineRedis::class, // one of these
                'type' => 'redis',     // files|memcache|redis|apc|xcache|none
                'host' => '127.0.0.1',
                'port' => 6379,
                'serializer' => \Redis::SERIALIZER_IGBINARY,
            ],
            'sid' => 'PROJECT_',       // key prefix
            'cache_flags' => [
                'config_options' => 3600,
                'site_template' => 3600,
                'iblock_include' => 3600,
            ],
        ],
        'readonly' => false,
    ],
    ```
    
    Different sections (`config_options`, `menu`, `site_template`, etc.) define TTL for internal kernel caches.
    
    ## Unmanaged Cache Template
    
    ```php
    $cache = \Bitrix\Main\Data\Cache::createInstance();
    $ttl = 3600;
    $cacheId = 'posts_list_' . md5(serialize($filter));
    $cacheDir = '/vendor_blog/posts';
    
    if ($cache->initCache($ttl, $cacheId, $cacheDir))
    {
        $data = $cache->getVars();
    }
    elseif ($cache->startDataCache())
    {
        $data = PostTable::getList([
            'filter' => $filter,
            'select' => ['ID', 'TITLE'],
        ])->fetchAll();
    
        // If conditions are not met — stop writing cache:
        if (empty($data))
        {
            $cache->abortDataCache();
        }
        else
        {
            $cache->endDataCache($data);
        }
    }
    ```
    
    - `cacheId` — unique key, includes all variables affecting the result.
    - `cacheDir` — cache "folder"; convenient to clear by directory `$cache->cleanDir($cacheDir)`.
    
    ## Managed Cache
    
    ```php
    $managed = \Bitrix\Main\Application::getInstance()->getManagedCache();
    
    if ($managed->read(86400, $cacheId, 'posts'))
    {
        $data = $managed->get($cacheId);
    }
    else
    {
        $data = $this->fetchExpensive();
        $managed->setImmediate($cacheId, $data); // or set() — write at the end of request
    }
    
    // Invalidation:
    $managed->clean($cacheId, 'posts');
    $managed->cleanDir('posts');
    ```
    
    ## Tags
    
    ```php
    use Bitrix\Main\Application;
    
    $taggedCache = Application::getInstance()->getTaggedCache();
    
    $taggedCache->startTagCache('/vendor_blog/posts');
    $taggedCache->registerTag('posts_list');
    $taggedCache->registerTag('post_42');
    $taggedCache->endTagCache();
    
    // Tag invalidation — clears all entries registered under this tag:
    $taggedCache->clearByTag('posts_list');
    ```
    
    Use your own tag names for HTML/component caches. There are **no** automatic TaggedCache tags like `ORM_<TABLE_NAME>`.
    
    ## ORM Query Cache
    
    ```php
    PostTable::getList([
        'select' => ['*'],
        'filter' => ['=ACTIVE' => 'Y'],
        'cache'  => [
            'ttl' => 3600,
            'cache_joins' => true, // cache JOIN queries
        ],
    ]);
    ```
    
    ORM auto-cache is stored under ManagedCache directories `orm_<table_name>` (see `Entity::getCacheDir()`). Invalidate via:
    
    ```php
    PostTable::cleanCache();           // DataManager / Table
    PostTable::getEntity()->cleanCache(); // Entity — ManagedCache::cleanDir('orm_...')
    ```
    
    Writes that change cacheable rows also call `cleanCache()` from the ORM layer. To clear related TaggedCache HTML, register and invalidate **your own** tags in event handlers — do not invent `ORM_*` tag names.
    
    ## Component Cache
    
    In `class.php` / `component.php`:
    
    ```php
    if ($this->startResultCache(false, [
        $USER->IsAuthorized(),
        $arParams['SECTION_ID'],
    ]))
    {
        $this->arResult['ITEMS'] = $this->fetchItems();
        $this->includeComponentTemplate();
    }
    ```
    
    Component parameters controlling cache:
    
    - `CACHE_TYPE`: `A` (autocache), `Y`, `N`.
    - `CACHE_TIME`: TTL in seconds.
    - `CACHE_GROUPS`: `Y` — key depends on user groups.
    
    ## Composite Cache
    
    Enable and configure Composite Site in Admin → Settings → Composite Site (or programmatically via `Bitrix\Main\Composite\Engine`). There is no separate "compression module" requirement for composite.
    
    Consider composite constraints: dynamic blocks are marked via `$APPLICATION->SetPageProperty('composite_frame_mode', 'Y')` / `setFrameMode`, personal data should not be in the static part, AJAX components are fetched with a separate request.
    
    ### Composite zones and NGINX
    
    - Static zone — full page HTML cache.
    - Dynamic zone (`data-dynamic`) — refreshed via AJAX on each hit.
    - Autocomposite vs manual composite — configure in Admin → Composite settings.
    - NGINX can serve static composite files directly; configure composite pool path (BitrixVM: *Configure nginx to use composite cache*).
    
    For ORM/SQL optimization see skill `bitrix-performance`.
    
    ## Invalidation by Events
    
    Typical scheme: `OnAfterUpdate`/`OnAfter*` handler in the tablet calls `$taggedCache->clearByTag(...)` for your tags, and/or `Table::cleanCache()` for ORM query cache. Use new ORM events via `EventResult` instead of `$GLOBALS['USER_FIELD_MANAGER']->...`.
    
    ## Antipatterns
    
    - Caching "live" data (balances, stock levels) with high TTL without invalidation.
    - Using global `$_SESSION`/`$USER` inside the cache key instead of explicit variables.
    - One shared `cacheDir` for all modules — hard to clear selectively.
    - Missing `abortDataCache()` for empty/error results.
    - Enabling composite without testing dynamic blocks.
    - Assuming TaggedCache tags `ORM_<TABLE>` exist — use `cleanCache()` / `orm_*` ManagedCache dirs instead.
    
    ## Checklist
    
    - [ ] Cache level selected: short-lived → unmanaged; rarely changing and critical → managed + tags.
    - [ ] Cache key includes all parameters affecting the result (filters, language, permissions).
    - [ ] Cache invalidation is automated via tags/events, not manual `cleanDir('/')`.
    - [ ] ORM query cache cleared via `Table::cleanCache()` / `Entity::cleanCache()`, not fictional `ORM_*` tags.
    - [ ] Component cache accounts for user groups where important.
    - [ ] Production environment uses Redis/Memcached instead of file cache.
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related