1C-Bitrix Website Development
When a project starts on Bitrix, the architectural decision made on day one determines the cost of maintenance for the next three years. A single info block for a catalog with 30 properties — and within a year b_iblock_element_property grows to millions of rows, CIBlockElement::GetList takes 4 seconds, and the faceted index doesn't help because linked properties never made it into b_catalog_sm_*. Restructuring on production means rewriting component templates, rebuilding filters, recreating SEO rules. It's cheaper to design it right once.
Info Blocks, Highload, D7 ORM — Choosing the Storage Model
This isn't an abstract question — it determines which components work out of the box and which you'll write from scratch.
Standard info blocks store properties in an EAV model: the b_iblock_element_property table, one row per value. For a catalog of 5K products with 10 properties, that's 50K rows — MySQL handles it fine. For 80K products with 25 properties — 2 million rows, JOINs during filtering start costing seconds. But info blocks give you built-in SEO tools, a visual editor, and ready-made catalog components.
Highload blocks use a flat table, one column per property. Indexes lay down cleanly, filtering across 200K records takes 30-80ms. But there's no familiar catalog.section, no property inheritance from sections, no built-in SEO module. For reference tables (cities, brands, units of measurement) — mandatory. For the main catalog — depends on volume and filtering complexity.
D7 ORM via Bitrix\Main\ORM\Data\DataManager — for entities that don't fit into either info blocks or Highload. Applications with ten relations, custom logs, period aggregations. Full control, but you build the admin panel yourself.
How Bitrix Differs from WordPress and Laravel
WordPress also uses EAV via wp_postmeta, but without built-in e-commerce at the sale module level. WooCommerce is a plugin, not the core. Bitrix provides the catalog module with trade offers (SKU), price types, inventory management, and 1C integration via CommerceML. For a company that lives in 1C:Enterprise, this argument outweighs everything else.
Laravel is a framework, not a CMS. Complete architectural freedom, but the catalog, shopping cart, access control, 1C integration — you write from scratch. On a project with a 4-6 month budget and a team of 3, Laravel is justified. For a corporate site with a catalog needed in 2 months — Bitrix is faster. Not better or worse — faster for typical tasks.
The fundamental difference is the component-based approach. A Bitrix component (bitrix:catalog.section, bitrix:news.list) is a ready-made bundle of controller + model + caching. You include it in a template, configure through $arParams, customize output in template.php. Business logic goes in result_modifier.php or in a custom module at local/modules/. Templates go in local/templates/. Never in the core.
Performance: What Gets Built In from the Start
You can optimize after launch. But it's expensive. Here's what gets designed into the architecture before the first commit:
Caching — three levels. Managed component cache ($arParams['CACHE_TIME']), shared cache via memcached or Redis, composite site via the composite module. Composite serves HTML without initializing the core — response time drops from 200ms to 15-30ms. But there are limitations: it doesn't work for authenticated users with personalized content without additional configuration.
Static assets — CDN for /upload/, /bitrix/js/, /bitrix/css/. WebP via CFile::ResizeImageGet() with conversion. Lazy loading for images below the fold. Moving static assets to CDN alone removes 40-60% of the load from the web server.
Database — composite indexes on frequently filtered properties. EXPLAIN on every heavy query before launch. If the catalog has more than 50K products — faceted indexes are mandatory: Bitrix\Catalog\Model\SmartFilter recalculates them via cron, filtering drops from 3 seconds to 50ms.
PHP — OPcache with JIT on PHP 8.1+, realpath_cache_size=4096K for Bitrix (many files — the standard 16K isn't enough). Check via the "Performance" → "PHP" panel — it shows whether everything fits in OPcache.
Typical Project Structure
The site template lives in local/templates/main/. Components are included via $APPLICATION->IncludeComponent(). Custom component templates go in local/templates/main/components/bitrix/. We never modify stock templates — they'll be lost on update.
Modular code structure:
-
local/modules/project.core/— business logic, helpers, service classes -
local/components/project/— custom components -
local/php_interface/init.php— event handlers, but minimal: module registration and autoloader, everything else goes in the module
Deployment — Git + migrations via sprint.migration. No FTP. Info block structure, highload blocks, email templates — everything in migrations, reproducible on any environment.
Stages
- Analysis and design (1-2 weeks) — functional requirements, data structure, page prototypes in Figma. Output: a specification describing info blocks, components, and integrations
- Design (1-3 weeks) — UI/UX, responsive layouts, component design system
- Development (3-8 weeks) — frontend, backend, integrations. Two-week sprints with staging demos
- Testing (1-2 weeks) — functional, cross-browser, load testing. PageSpeed, Lighthouse, WebPageTest checklist
- Launch and stabilization (3-5 days) — deployment, monitoring, fixing first-day issues
| Project Scale | Estimated Timeline |
|---|---|
| Corporate site, 10-20 pages | 6-10 weeks |
| Catalog with filtering, up to 10K products | 8-14 weeks |
| Online store with 1C integration | 12-20 weeks |
| B2B portal with personal account | 14-24 weeks |
Timelines depend on the number of integrations, filtering complexity, and content volume. Cost is determined after requirements analysis — too many variables for template figures.
Common Mistakes We See in Audits
-
Business logic in
template.php— discount calculations, permission checks, price formatting right in the component template. Impossible to test, impossible to reuse. We move it toresult_modifier.phpor a module service class -
Direct SQL queries via
$DB->Query()instead of D7 ORM — you lose caching, type safety, and injection protection -
A single giant
init.phpat 2000 lines — event handlers, helpers, classes — all in one file. Works until you need to debug a specific handler. We move it to a module with autoloading -
Cache without tags — a component caches for an hour, but data was updated 5 minutes later. Tagged cache via
$this->SetResultCacheKeys()andCIBlock::clearIblockTagCache()solves the problem -
Core updates without staging — updated on production, the
catalogmodule changed discount calculation logic, the cart broke. Always staging first, then production







