Architecture of 1C-Bitrix Projects
A wrong storage choice — and a catalog with 80K products takes 5 seconds to render a page. Fail to externalize sessions — and when you add a second web server, users start "dropping out" of their carts. Architectural mistakes in Bitrix don't forgive — they accumulate and a year later turn into a major refactoring effort.
Infoblocks vs Highload Blocks: A Decision You Can't Undo
This is the first and most expensive architectural decision. Migrating from infoblocks to Highload later means rewriting all components, templates, filters, and search indexes.
Standard infoblocks work through the tables b_iblock_element and b_iblock_element_property. Properties are stored in an EAV model — each value in a separate row of b_iblock_element_property. With 50 properties and 100K elements, you get 5 million rows in a single table. MySQL starts choking on JOINs during filtering.
Infoblocks are good for:
- Content up to 10–50K elements — articles, news, promotions
- Entities that need the visual editor and SEO module
- Elements with property inheritance from sections
Highload blocks are flat tables. One entity — one table with columns. No EAV. Filtering on indexed columns works an order of magnitude faster. A catalog of 200K products with a faceted index (b_catalog_sm_*) returns filter results in 50ms instead of 3 seconds.
When Highload is mandatory:
- Catalogs with 50K+ products
- Reference tables queried on every page load (cities, brands, specifications)
- Write-heavy data — logs, submissions, history
- Entities requiring direct SQL queries and aggregations
D7 ORM and custom tables — for business logic that doesn't fit the infoblock model. Many-to-many relationships, computed fields, custom aggregations. Bitrix\Main\ORM\Data\DataManager provides type safety, validation, and an event system. But you'll have to build the admin interface from scratch.
| Criterion | Infoblocks | Highload | D7 ORM |
|---|---|---|---|
| Data volume | Up to 50K | 50K–10M+ | Any |
| Filtering speed | Degrades with growth | Stable | Maximum |
| Structure flexibility | High (EAV) | Medium (fixed) | Full |
| Admin UI out of the box | Yes | Yes | No |
| SEO module support | Yes | Limited | No |
Scaling: How Not to Go Down on Black Friday
Horizontal scaling is the topic where 90% of projects fail. Because they think about it when the site is already down.
First step — move sessions from files to Redis. Without this, a second web server is useless: the user logs in on server A, the next request goes to server B, session not found — logged out. In .settings.php:
'session' => ['value' => ['mode' => 'redis', 'host' => '127.0.0.1', 'port' => 6379]]
Next:
- nginx upstream or HAProxy distributes requests. Bitrix's "Web Cluster" module supports clustering, but requires a "Business" license or higher
-
CDN for static assets —
/upload/, JS, CSS. The server stops spending resources on serving images -
MySQL replication — master for writes, slave for reads. Bitrix supports up to 9 slave connections via
.settings.phpconfiguration. But there's replication lag — a product is added, but appears on the slave 0.5–2 seconds later
Vertical scaling — cheaper and faster to start:
-
EXPLAINon every heavy query. A single composite index onb_iblock_element_property(IBLOCK_PROPERTY_ID, VALUE) speeds up filtering by 10x - Multi-level cache: Bitrix managed cache → memcached → composite site. Check the
hit ratein the "Performance" panel — if below 90%, something's wrong - OPcache with JIT on PHP 8.1+ — free 15–30% speedup
Microservices on Top of a Monolith
Bitrix is a monolith, and that's fine. Breaking it into microservices is madness. But extracting heavy processes — that's the right move.
Import/export — the most common pain point. Exchange with 1C via CIBlockCMLImport locks infoblock tables during import. 100K products means 20–40 minutes when catalog filtering on the site is sluggish. Solution: move the import into a separate worker via RabbitMQ, write to an intermediate table, then atomically switch.
-
Search — Elasticsearch instead of the built-in
search.title. Full-text and faceted search, autocomplete, typo correction. Load on MySQL is completely eliminated -
Notifications — push, SMS, email via queue.
CEvent::Send()is synchronous — until the email is sent, the user waits for the server response. A queue solves this - Report generation — PDF, Excel on large volumes. In a separate process, the result is a download link
API-First: REST, GraphQL, Webhooks
Bitrix REST API (/rest/) covers CRM, tasks, drive, but doesn't cover the catalog and infoblocks to the extent needed. For SPAs on React/Vue, you have to write custom endpoints via Bitrix\Main\Engine\Controller.
- GraphQL — for mobile apps where bandwidth is expensive. The client requests only the fields it needs
- Webhooks — event-driven model: new order → POST to external URL. No need to poll the API every 5 minutes
-
Versioning —
/api/v1/,/api/v2/. Without it, an API update breaks all consumers simultaneously - OpenAPI/Swagger — auto-generated documentation. An API without documentation is forgotten by even the author within a month
Documentation: ADRs Instead of Word Files
- ADR — Architecture Decision Records. A short file: context, decision, consequences. "Why did we choose Highload for the catalog?" — a year later, a new developer opens the ADR and understands in 5 minutes, instead of guessing for three days
- Diagrams — servers, data flows, integration points. PlantUML or Mermaid, stored in the repository alongside the code
-
ER diagrams — infoblocks, properties, relationships. Without a schema, even the author won't remember after six months why the
LINKED_PRODUCTSproperty references another infoblock via binding rather than a Highload reference - Runbook — deployment, rollback, scaling, incident response. Because the incident will happen Saturday night when the architect is unreachable
Tech Debt: Legacy Core, Raw SQL, Logic in Templates
Tech debt in Bitrix is specific. Three main sources:
-
Legacy core instead of D7 —
CIBlockElement::GetList()instead of\Bitrix\Iblock\Elements\ElementTable::getList(). The legacy core doesn't support ORM features, is slower, and Bitrix will eventually deprecate it -
Raw SQL in component templates —
$DB->Query("SELECT...")right intemplate.php. We move it to service classes, replace with ORM -
Business logic in
result_modifier.php— a file that should prepare data for the template, not calculate discounts and check access permissions
Approach: PHPStan level 5+ for issue detection, a "business impact / fix cost" matrix, incremental refactoring per sprint. Not everything at once — but the trend must be downward.
Our Process
- Requirements gathering (3–5 days) — load, growth plans, integrations, budget
- Design (1–2 weeks) — data structures, integration schema, ADRs for key decisions
- Prototyping (1 week) — load tests on real volumes. A Highload block with 200K records and 30 properties — will the filtering hold?
- Documentation (3–5 days) — diagrams, runbook, API specifications
- Review (2–3 days) — internal, then with the client
The deliverable is an architectural document that serves as the foundation for development, estimation, and scaling.







