Optimizing Page Rendering in 1C-Bitrix
Optimizing Page Rendering in 1C-Bitrix
PageSpeed Insights shows a score of 38 with an LCP of 4.2 seconds. TTFB is 1.8 s, yet the full HTML content has already been delivered. The problem is not the network or client-side JS — the page is being assembled slowly on the server. Bitrix provides diagnostic tools, but they are rarely used correctly.
Diagnosing with Standard Bitrix Tools
Enable the debug panel: $_GET["show_page_exec_time"] or via a constant in dbconn.php:
define('SHOW_PAGE_EXEC_TIME', true);
define('SHOW_SQL_STAT', true);
The panel in the page footer will show:
- total execution time
- number of SQL queries and their total time
- memory consumed
A typical picture of a problematic page: 400+ SQL queries, 1.5–2.5 s on SQL with only 0.3 s on PHP. Components are running in inconsistent caching modes.
Profiling Components
Bitrix does not have a built-in profiler at the component level. Use microtime() around component calls:
// local/php_interface/init.php
AddEventHandler('main', 'OnBeforeEpilog', function() {
global $APPLICATION;
if (defined('SHOW_PAGE_EXEC_TIME') && SHOW_PAGE_EXEC_TIME) {
$timers = \Bitrix\Main\Diag\Helper::getTimers();
arsort($timers);
echo '<pre>Top components by time:';
array_splice($timers, 10);
print_r($timers);
echo '</pre>';
}
});
An alternative is Bitrix Performance Monitor (a Marketplace module) or xhprof/Tideways via a wrapper.
The Main Causes of Slow Rendering
Component with No Cache or CACHE_TYPE = NONE
$APPLICATION->IncludeComponent('bitrix:catalog', '.default', [
'CACHE_TYPE' => 'N', // <- performance killer
]);
Change to:
'CACHE_TYPE' => 'A', // automatic based on site settings
'CACHE_TIME' => 3600, // seconds
For components that depend on user context (cart, personal account), component-level caching does not work — use an AJAX approach here: serve the template from cache and load personal data in a separate request.
N+1 in Component Templates
The most common cause of 400+ queries — a loop over results with a query inside:
// Bad: one query per element
foreach ($arResult['ITEMS'] as &$item) {
$item['SECTION'] = \CIBlockSection::GetByID($item['IBLOCK_SECTION_ID'])->GetNext();
}
Fix — an aggregated query before the loop:
$sectionIds = array_unique(array_column($arResult['ITEMS'], 'IBLOCK_SECTION_ID'));
$sections = [];
$res = \CIBlockSection::GetList([], ['ID' => $sectionIds], false, ['ID', 'NAME', 'CODE']);
while ($s = $res->GetNext()) {
$sections[$s['ID']] = $s;
}
foreach ($arResult['ITEMS'] as &$item) {
$item['SECTION'] = $sections[$item['IBLOCK_SECTION_ID']] ?? null;
}
Disabled Caching in a Composite Component
A composite component (e.g., bitrix:catalog) manages caching for its children. If the section settings have "Do not cache" selected — caching is disabled for the entire tree, including the product listing sections.
Check in site settings: Settings → Product Settings → Caching.
Template Optimization
PHP template minification. Bitrix assembles a page from dozens of include calls. Each include hits the filesystem. On HDD servers this is 5–15 ms per file. Solution — OPcache with opcache.validate_timestamps=0 in production (manual cache invalidation after deploy).
Moving heavy blocks to AJAX. Widgets like "similar products," "recently viewed," and "popular in category" are candidates for AJAX loading. The main page renders quickly; widgets are loaded in parallel.
Composite site. The built-in Bitrix mechanism for caching entire pages with dynamic block substitution (cart, authentication). Delivers TTFB of 50–100 ms for authenticated users. Requires setup per specific template — it cannot be enabled with a single button without adapting components.
Example Result
An online building materials store, 180,000 SKUs. Before optimization: TTFB 2.1 s, 380 SQL queries on a category page. After: CACHE_TYPE=N disabled in three components, two N+1 issues fixed, OPcache validate_timestamps=0 enabled. Result: TTFB 420 ms, 38 SQL queries, LCP 1.9 s.
Scope of Work and Timeline
| Phase | Content | Timeline |
|---|---|---|
| Audit | Profiling top 5 pages, identifying bottlenecks | 1–2 days |
| Cache optimization | Configuring component caching | 1–2 days |
| N+1 elimination | Refactoring templates with aggregated queries | 2–5 days |
| Composite | Template setup and adaptation | 2–4 days |







