Optimizing the exchange speed of 1C and 1C-Bitrix

Our company is engaged in the development, support and maintenance of Bitrix and Bitrix24 solutions of any complexity. From simple one-page sites to complex online stores, CRM systems with 1C and telephony integration. The experience of developers is confirmed by certificates from the vendor.
Our competencies:
Development stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1175
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Website development for FIXPER company
    811
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Development based on Bitrix, Bitrix24, 1C for the company Development of an Online Appointment Booking Widget for a Medical Center
    564
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Development based on 1C Enterprise for MIRSANBEL
    747
  • image_crm_dolbimby_434_0.webp
    Website development on CRM Bitrix24 for DOLBIMBY
    655
  • image_crm_technotorgcomplex_453_0.webp
    Development based on Bitrix24 for the company TECHNOTORGKOMPLEKS
    976

Optimizing 1C and 1C-Bitrix Exchange Performance

An exchange with 50,000 products taking 4 hours and grinding the entire site to a halt during business hours is not normal — it is a symptom. The typical cause: the exchange was configured long ago for 5,000 products, the catalog grew tenfold, and the settings were never revisited. Exchange optimization is a complex effort on both sides of the integration.

Profiling: Finding the Bottleneck

Before optimizing anything — measure. Add timestamps to the exchange log:

// In the OnIBlockElementImport handler
$timings[] = [
    'step'    => 'element_import',
    'element' => $elementXmlId,
    'time'    => microtime(true) - $startTime,
];

After the exchange, analyze where 80% of the time is spent. Common culprits:

  • XML parsing — files are too large, not split into chunks
  • Database writes — indexes, triggers, unoptimized INSERTs
  • Price recalculation — if automatic price rule recalculation is enabled
  • Search indexing — rebuilding the search index on every change

Optimizing XML Parsing

Split the export into batches. In 1C settings, set "Number of elements per file" = 1000–2000. Each file is processed by a separate HTTP request. 1C-Bitrix processes a file in 30–60 seconds instead of hanging for 2+ hours.

Enable ZIP compression. A file with 2,000 products uncompressed is 8–15 MB; compressed it is 1–3 MB. This matters significantly for the channel between 1C and the hosting server, especially over a slow connection.

In 1C publication settings:

Use data compression: Yes
Compression threshold: 1024 bytes

Optimizing Database Writes

The standard 1C-Bitrix import calls CIBlockElement::Add/Update for each element — a full cycle including validation, event handlers, and cache invalidation. For 50,000 elements that means 50,000 separate transactions.

Disable unnecessary events during import:

// Before import
define('BX_BUFFER_MESS', true); // suppress email notifications
$GLOBALS['STOP_STATISTICS'] = true; // skip statistics updates
define('NO_AGENT_STATISTIC', true);

Deferred re-indexing. Search is re-indexed after every element change. For bulk imports — disable auto-indexing and trigger re-indexing as a separate agent after the exchange completes:

// Temporarily disable indexing
\Bitrix\Main\Config\Option::set('search', 'indexer_auto_mode', 'N');

// After the exchange, trigger re-indexing
CSearch::ReIndexAll(true, CATALOG_IBLOCK_ID);

Deferred cache invalidation. Instead of calling BXClearCache on every element update — collect changed elements into an array and invalidate the cache in a single batch at the end of the exchange.

Optimizing Database Queries During Import

When updating an element, 1C-Bitrix performs a SELECT to check for existence, then an UPDATE or INSERT. In a bulk import, you can preload all XML_IDs into memory and avoid per-element SELECTs:

// Fetch all existing elements in a single query
$existing = [];
$res = CIBlockElement::GetList(
    [],
    ['IBLOCK_ID' => CATALOG_IBLOCK_ID],
    false,
    false,
    ['ID', 'XML_ID']
);
while ($el = $res->Fetch()) {
    $existing[$el['XML_ID']] = $el['ID'];
}

// During import: isset($existing[$xmlId]) instead of SELECT

Splitting the Exchange by Data Type

Running a full exchange (catalog + prices + stock) in a single session is wasteful. Split it into independent streams:

Stream Contents Frequency Load
Full catalog Descriptions, properties, images Once/night High, overnight
Prices offers*.xml with prices only Every hour Low
Stock offers*.xml with stock only Every 15 min Minimal
Orders orders.xml Every 15–30 min Minimal

In 1C, multiple independent scheduled tasks can be configured for different export types.

Caching on the 1C-Bitrix Side

Review the cache settings in the catalog module:

Settings → Product Settings → Performance:

  • Catalog element cache: enable, TTL 3600 seconds
  • Property cache: enable
  • Trade offer cache: enable for stores with product variants

During the exchange, cache is automatically invalidated for changed elements. If invalidation takes a long time — check the cache size on disk (/bitrix/cache/iblock/) and increase memory_limit if necessary.

Case Study: Reducing Exchange Time from 4 Hours to 25 Minutes

An auto parts online store with 65,000 SKUs. The exchange ran once a day and took 4+ hours, blocking price recalculation for that entire period.

Root causes identified:

  1. The entire catalog in a single XML file (240 MB)
  2. Search re-indexed on every element
  3. Price recalculation against 12 rules on every price change
  4. BXClearCache for the entire infoblock every 100 elements

After optimization:

  • Catalog split into files of 2,000 elements each
  • Deferred re-indexing via a separate agent
  • Price recalculation only after import completion, not during
  • Batch cache invalidation at the end of the session

Result: full exchange — 25 minutes. Stock and price exchange only (every hour) — 3–4 minutes.

Optimization Timelines

Task Duration
Profiling and analysis of the current exchange 4–8 hours
Batch splitting + ZIP 2–4 hours
Deferred re-indexing + cache 1 day
Splitting into independent streams 1–2 days
Full audit + custom import with batch writes 3–5 days