Optimizing Queries to 1C-Bitrix Highload Blocks

Catalog and checkout slow down when property selection hits Highload blocks. We optimize Highload blocks turnkey: we configure indexes, caching, and storage structure so pages respond noticeably faster. As a result, server load decreases and customers don't leave due to slow loading.

Our competencies:

Frequently Asked Questions

Why Highload blocks slow down the catalog and orders

Highload blocks in 1C-Bitrix are tables not tied to information blocks, designed for tens and hundreds of thousands of records: prices, stock levels, product-to-warehouse links, order status history.

While there are few records, querying by property is fast, and no one notices that a mine has already been planted under the hood. Optimizing Highload blocks begins with understanding what exactly turns a convenient abstraction into a bottleneck.

The problem manifests as the number of records grows. A developer adds a filter by a custom property, and there is no index on it — so the database reads the entire table instead of doing a targeted lookup.

One such query on a product page turns into hundreds when crawling the catalog, and response time stretches into seconds. Slow catalog queries almost always mean one thing: fetching Highload block properties is done via a full scan rather than by index.

The load on the database grows non-linearly. Every extra scan holds a connection, the DBMS cache gets evicted, and neighboring sections suffer — the cart, checkout, and user account.

A traffic spike or stock synchronization finishes the job: the site starts returning timeouts exactly where sales are lost.

Next, we break down how this gets fixed: where to add composite indexes, how to rewrite the fetch using batch queries, what to move into the cache, and how to establish a process so that the growth in the number of records no longer brings down the catalog.

What Highload Block optimization delivers

Highload blocks in 1C-Bitrix are tables not tied to information blocks, designed for hundreds of thousands and millions of rows. While the catalog is small, the difference is unnoticeable.

But as soon as a filter by property, sorting, or a subquery against a related table enters the selection, query time grows non-linearly: what responded instantly on a test database starts hitting a full table scan on production. The catalog "lags" precisely at the moments when it receives its main traffic.

Highload Block optimization is work on how data physically resides and how code queries it.

We put indexes in order for real filtering scenarios, remove "brute-force" selections through ORM where a targeted query is needed, cache reference data that doesn't change between requests, and spread heavy operations out over time.

As a result, the catalog's response speed stops depending on how many products are in the database and how many filters the user has selected.

A separate effect is resilience to peak loads. When each request to the catalog stops occupying a database connection for long seconds, the server calmly handles concurrent requests that previously led to queues and timeouts.

The load removed from the server is not an abstraction: the freed-up resources go toward serving pages and processing orders, rather than waiting for a response from the database.

We don't guess, we measure: we capture query time on real scenarios before and after, look at which queries remain heavy, and close exactly those.

This way, Highload Block optimization delivers predictable catalog response and headroom for load to accommodate future assortment growth.

Acceleration methods: indexes, cache, denormalization

A highload block is a table in the database, and the speed of fetching from it is determined by how the indexes are structured and how often we go to the database for the same data.

Below are three working approaches that we use on 1C-Bitrix projects, and their limitations: there is no universal method, the choice depends on the load profile.

Approach When it fits Limitations
Composite indexes Frequent filters by 2-3 fields simultaneously, sorting by one of them Slows down writes; the index must be designed for specific queries, not "just in case"
Caching query results Reference data that is read often and changed rarely Invalidation: when the block is updated, the cache must be reset, otherwise the user sees stale data
Denormalization Heavy JOINs between blocks, repeated computed fields Data duplication and the risk of desync — synchronization logic is needed on write

A composite index works only if the order of fields in it matches the order of conditions in the query: an index on (city, date) will speed up the "city + date" filter, but will not help when fetching by date alone.

That is why we first capture real queries from the logs, and only then design the index — otherwise we get extra write load with no gain on reads.

Caching query results gives the greatest effect on reference tables: if a block changes once a day but is read thousands of times, the cache removes almost all the load from the database.

Denormalization is a last resort: it eliminates the JOIN, but moves the complexity into the write code, and without careful synchronization the data diverges.

In practice we combine them: indexes for point filters, cache for repeated reads, denormalization — only where the JOIN has truly become a bottleneck.

How we carry out optimization: stages of work

Optimizing a Highload block is not "turn on caching and wait," but a sequence of measurable steps. Each stage ends with an artifact: a report, a modified configuration, or a test that can be repeated.

Below is what the work looks like from the first request to handing over the regulations to your team.

  1. Request audit. We collect real traffic to the Highload block: which queries come from components, which filters and sorts by properties are used most often, where queries are duplicated on a single page. The output is a "page → query → frequency" map, which shows what to optimize first.

  2. Profiling. We measure the time of each query and the number of database calls on typical scenarios: detail page, catalog, search, export. We look separately at queries that run in a loop — these are the ones that cause the main slowdown as data grows.

  3. Index configuration. For frequent filters and sorts, we add indexes to the Highload block itself, remove unnecessary ones, and rebuild the order of fields in composite indexes. We verify that the query goes through the index rather than a full table scan.

  4. Reworking queries. We eliminate queries in a loop, merge duplicate ones, limit the set of fields, and switch heavy scenarios to paginated loading. We cache only what truly changes rarely — otherwise we end up with stale data on detail pages.

  5. Load testing. We run the scenarios on a volume close to production and with headroom for the number of concurrent users. We look not only at average response time, but also at behavior at peak: where queues appear and how the database behaves.

  6. Handing over regulations. We document the modified indexes, caching rules, and the list of queries that must not be returned to the code. Your team receives a document that ensures new changes do not break the speed already achieved.

The order is exactly this: indexes without an audit are often placed on the wrong fields, and load testing without profiling does not show what became the bottleneck. Describe your task — we will come back with an estimate and a work plan based on these stages.

What the client receives

Highload block optimization does not end with code changes — it ends with handing over a working configuration and clear instructions to the client.

Below is what your team retains after the project: not an abstract "report," but a set of artifacts that let you operate and evolve the system without us.

  • Highload block index schema — which fields are indexed, composite indexes and their order, and the rationale for specific queries. Indexes that can be dropped without losing speed are flagged separately, so the database does not grow "just in case."
  • Cache configuration — which queries are cached, their lifetime, and binding to tags and reset events. It specifies what gets invalidated when entities change and what persists until a scheduled refresh.
  • Map of heavy queries — a list of calls to Highload blocks with before-and-after timing measurements, so it is clear exactly where the load went, rather than "it got faster overall."
  • Maintenance schedule — frequency of index rebuilds, table growth checks, slow query monitoring, and checkpoints for scheduled analysis. Tied to events: catalog population, imports, seasonal traffic growth.
  • Structure documentation — a description of fields, relationships, and query logic: what is stored in Highload blocks and why, and which relationships are critical. A new developer onboards via the document, not via chat history.
  • Rollback instructions — which changes are reversible, where the original configuration versions are stored, and how to restore previous behavior without data loss.
  • Post-release verification checklist — a set of control measurements your team can use to independently confirm that the optimization holds up under load.

Each artifact is tied to the project's actual files and settings, not to a generic manual. Describe your task — we will come back with an estimate and a plan for which items on this list we will address first.

Case study: property selection accelerated 6x

A catalog on 1C-Bitrix with high-load blocks: product properties were stored in an HL block, and each product card pulled them with a separate query.

With 40,000 items and filters across 8 properties, the catalog page took 4.8 seconds to build, and under a load of 300 concurrent visitors the selection time reached 9 seconds — some queries timed out, and the catalog served empty tiles.

What it was before

The problem was not the volume of data, but the access pattern. The code iterated over products in a loop and hit the HL block for properties on every iteration — a classic N+1.

There were no indexes on custom fields, and the filter built conditions on unindexed columns, so the database scanned the entire table. Caching did not help: it was invalidated on any price or stock change, that is, almost constantly.

What was changed

Property selection was rewritten as a single batch query with a filter by an array of identifiers instead of a loop — instead of a hundred database calls per page, only one remained.

Composite indexes were added for the actual filter combinations, and rarely changing properties were moved into a separate cache layer with a long lifetime. Heavy aggregates for sorting were precomputed and are updated on the product change event rather than on every render.

What it became

Property selection time on the catalog page dropped from 4.8 to 0.8 seconds — a 6x improvement. Under a load test of 300 concurrent visitors, response time stays within 1.3 seconds, there are no timeouts, and the catalog serves complete product cards.

Database costs stopped growing along with the assortment: adding new items no longer lengthens selection linearly, because the number of queries per page does not depend on the number of products.

The catalog's resilience was confirmed by a repeated load test after deployment — at the peak of a sale, behavior does not differ from the test bench.

How is a Highload block different from an information block?

An information block and a Highload block solve different tasks, and confusing the two is the most common cause of performance degradation on Bitrix.

An information block is a content entity: it has section binding, properties, site binding, permissions, versions, a search index, and the entire accompanying layer.

A Highload block is a flat database table with minimal scaffolding: just fields and indexes, no sections, no search index, no unnecessary JOINs.

The difference shows up at scale. While an information block holds dozens or hundreds of records, the choice of storage barely affects response time.

When the count runs into hundreds of thousands and millions of rows — city directories, order history, product-to-attribute bindings — the information block starts to slow down: a query drags service tables along with it, and filtering by properties goes through separate relations.

A Highload block is read directly from its own table, and a query on an indexed field completes in predictable time regardless of how many rows sit next to it.

The data structure here is the optimization. In a Highload block you define the field types and indexes yourself, so a composite index on a pair like "product + attribute" or "user + date" removes the main load.

In an information block such control is limited: some filters go into properties, and those are stored separately and joined on every query.

Hence the typical scenario: reference and linking data is moved to a Highload block, while the storefront, sections, and everything edited through the interface stays in the information block.

The reverse mistake is just as costly. If you put into a Highload block something that is by nature content — articles, pages, products with sections — you lose the standard output mechanisms, permission inheritance, and search, and then you have to write them in manually.

The choice of storage is determined not by fashion but by how the data is read: if you need mass selections by indexed fields and the volume is growing — a Highload block; if you need content with sections, permissions, and an editorial interface — an information block.

In practice, systems are almost always hybrid: the information block handles content, the Highload block handles reference data and links between entities.

We analyze the data structure and the query profile before changing anything — that way the migration touches only those tables where it actually delivers a gain in response time.

Common technical concerns

Highload blocks in 1C-Bitrix are tables in a separate database designed for high load: queries go directly, without an ORM layer, and any mistake in indexes or caching shows up immediately in production. Below are the points most often clarified before starting optimization work.

Which indexes are needed, and will adding them break current queries?

We build an index for a specific query pattern: the set of fields in WHERE, the sort order, range conditions. Adding an index does not change the query result — the planner either starts using it or keeps the previous plan, so there is no data regression.

The risk is different: extra indexes slow down inserts and updates. That is why we first capture real queries from the logs rather than adding indexes "just in case," and after verification we remove the unused ones.

Will the cache have to be flushed on every data update?

No, if caching is done with the right key. We tie the cache to the query parameters and to tags that change together with the data: a record is updated — only the related part is invalidated, the rest stays alive.

A full flush is needed only in a targeted way, when the block structure or the set of fields changes. This approach eliminates constant cache misses and reduces the load on the database severalfold.

Are the changes compatible with the current code and platform updates?

Yes. We do not touch the core and do not modify stock components — we work through our own handlers, index settings, and cache configuration. Platform and module updates proceed as usual, because the changes live outside the updated files. Before rollout we run the key scenarios on a copy and compare the output before and after.

How do we roll back if something goes wrong?

Each step is a separate change with a return point: indexes are removed with a single command, cache settings are reverted to their previous values, code changes go through a version control system.

We roll out in stages, measuring response time at each step, so a rollback takes minutes and does not require taking the site down.

Let's discuss your optimization task

To come back with an assessment and a plan rather than generalities, we need a minimum of input about your configuration.

Optimizing highload blocks almost always comes down to how indexes are structured, which queries run with filters and sorting, and how often the data changes — this determines what will have an effect: rebuilding indexes, caching query results, or moving part of the logic to a separate layer.

Send whatever you have on hand — we'll figure out the rest ourselves:

  • task description: where exactly it's slow — catalog, filter, personal account, export, integration with 1C;
  • structure of highload blocks: which fields, which relations, approximate volume of records and growth rate;
  • examples of heavy queries or an export from the slow query log;
  • how caching and data updates are currently set up — on a schedule, on an event, manually;
  • access to a staging environment or test contour where the load can be reproduced without risk to the production site;
  • constraints: the window during which work is allowed, and what must not be touched in the current logic.

If you don't have exact data — no problem: describe in words what's happening and when it started.

We'll ask clarifying questions about indexes, composite queries, and the link with 1C, and after the audit we'll come back with a work plan, timelines, and the improvement in response time it delivers. Describe your task — we'll discuss the details and propose a solution.