WordPress Blocks Don’t Scale. Here’s How a Registry System Fixes It.

A post on r/ProWordPress this week sparked a discussion that resonated with every developer building block-heavy WordPress sites: “WordPress blocks don’t scale. We built a registry system to fix it.” The thread had developers sharing their own experiences with block editor performance degradation, inserter bloat, and the maintenance nightmare of managing dozens of custom blocks across themes and plugins.

The core problem is real. WordPress’s block registration system was designed for a world where a theme might register five to ten custom blocks. When you push that to 30, 50, or 100+ blocks across a theme, multiple plugins, and block pattern libraries, the system starts to strain. The block inserter becomes slow and cluttered. Editor initialization takes longer. The JavaScript bundle size grows linearly with every registered block. And maintaining the codebase becomes a version control nightmare.

A registry system solves these problems by adding an organizational layer between your blocks and WordPress’s registration system. Here is how to build one that actually works at scale.

Why Block Registration Breaks at Scale

WordPress registers blocks by loading their JavaScript assets on every editor page load. Each block registered with register_block_type on the PHP side and registerBlockType on the JavaScript side adds to the initialization cost. At 10 blocks, this is invisible. At 50 blocks, editor load time increases noticeably. At 100+ blocks, you are shipping a megabyte or more of JavaScript just for block registration code before any actual content editing begins.

The block inserter compounds the problem. Every registered block appears in the inserter panel. Without organization, users scroll through a flat list of 100+ blocks trying to find the one they need. Categories help, but categories themselves become unwieldy when you have 15 of them. The discoverability problem makes the user experience worse as the block library grows, which is the opposite of what a good system should do.

Maintenance is the third scaling problem. Each block has its own directory with edit.js, save.js, block.json, style.css, and editor.css. At 50 blocks, that is 250+ files to maintain. Version updates, dependency changes, and WordPress core updates require touching every block. Without a centralized system, keeping blocks consistent in style, behavior, and quality becomes a manual process that invites drift.

What a Block Registry System Does

A registry system is an abstraction layer that manages block registration, loading, and organization. Instead of each block independently registering itself, all blocks register through a central registry that controls when and how they load. The registry provides:

Lazy loading. Blocks are registered with the WordPress editor only when they are needed, not all at once on page load. The registry knows which blocks exist but defers loading their JavaScript and CSS until the user actually inserts one or opens a page that contains one. This reduces initial editor load time proportionally to the number of blocks that are not actively used on the current page.

Categorization and discovery. The registry organizes blocks into logical groups with metadata that the inserter can use for better filtering, search, and recommendation. Instead of dumping 100 blocks into the inserter, the registry can surface blocks contextually based on what the user is editing, what blocks they use most, and what blocks are relevant to their role.

Dependency management. When blocks share dependencies, styles, or utility functions, the registry manages those shared resources centrally. One copy of the animation library, one copy of the icon set, one copy of the color picker component, shared across all blocks that need them.

Version control and updates. The registry tracks block versions, enabling rollback, A/B testing of block variations, and gradual rollout of block updates. When you update a block, the registry ensures backward compatibility by maintaining the previous version alongside the new one until deprecated.

Building the PHP Registry

The PHP side of the registry handles block type registration with WordPress and manages which blocks are available in different contexts. A basic registry class provides methods to register blocks from a blocks directory, filter which blocks are available based on post type or user role, and control asset loading.

The registry scans a designated blocks directory, reads each block’s block.json metadata, and stores the information without immediately registering the block with WordPress. Registration happens lazily, triggered by the editor requesting block data or by a page containing a specific block type.

Each block’s block.json is extended with custom metadata fields that the registry uses for organization: a group field for logical categorization beyond WordPress’s built-in categories, a context field that specifies which post types or editing contexts the block should appear in, a priority field that controls the order in the inserter, and a lazy field that indicates whether the block should be loaded on demand or eagerly.

The filter method allows the registry to conditionally exclude blocks based on the current editing context. A block designed for the site editor’s template editing mode should not appear in the post editor. A block designed for WooCommerce product pages should not clutter the inserter when editing a blog post. The registry handles these exclusions centrally rather than requiring each block to implement its own visibility logic.

Building the JavaScript Registry

The JavaScript side handles the actual editor integration: registering blocks with the block editor, managing the inserter presentation, and loading block assets on demand.

The key technique is dynamic imports. Instead of importing all block code at the top of your entry file, which forces webpack to bundle everything together, each block’s edit and save components are loaded dynamically when needed. The registry provides a loading component that displays a placeholder while the block’s code is being fetched.

Dynamic imports combined with webpack’s code splitting produce a separate JavaScript chunk for each block. The editor loads a small registry bundle on initialization, and individual block bundles are loaded on demand when the user inserts a block or navigates to a page containing one. For a theme with 80 blocks where a typical page uses 10, this reduces initial JavaScript payload by roughly 85%.

The inserter integration uses WordPress’s block collections API to group registry-managed blocks into well-organized sections. Each group defined in the registry maps to a block collection with a custom icon and label. The inserter presents these collections as expandable sections rather than a flat list, making it practical to navigate even very large block libraries.

Organizing a Large Block Library

Organization is where the registry provides the most practical value for teams maintaining large block libraries. A consistent file structure, naming convention, and metadata schema makes the difference between a manageable block library and an unmaintainable one.

The recommended structure groups blocks by functional area. Layout blocks that control page structure go in one group. Content blocks that display text, media, and data go in another. Interactive blocks that handle forms, tabs, and accordions have their own group. Commerce blocks for product displays and cart functionality are separated. Each group corresponds to a directory in the file system and a collection in the inserter.

Within each group, individual blocks follow a consistent structure: the block.json metadata file, the edit component, the save component or render.php for dynamic blocks, the stylesheet, and the editor stylesheet. The registry’s scanning function expects this structure and flags blocks that deviate from it during development.

Naming conventions enforce consistency across the library. Block names follow the pattern namespace/group-blockname. CSS classes follow wp-block-namespace-group-blockname. File names match the block name. When every block follows the same convention, finding, modifying, and debugging blocks becomes predictable regardless of who built them.

Performance Impact

The performance improvements from a well-implemented registry system are measurable and significant:

Editor initialization. A theme with 60 custom blocks that registers all of them eagerly adds roughly 300-500ms to editor initialization on typical hardware. The same theme with lazy registration through a registry adds approximately 50-80ms. The difference is the JavaScript parsing and execution time for 60 block bundles versus one small registry bundle.

Inserter performance. The block inserter renders every registered block type when opened. At 100+ blocks, the initial render causes a visible delay. Registry-based block collections render incrementally by group, and the search function queries registry metadata rather than rendering everything. The inserter feels fast regardless of library size.

Page load for visitors. Front-end performance improves because the registry ensures that only the CSS and JavaScript for blocks actually present on the page are loaded. Without a registry, many themes load all block styles unconditionally. The registry’s dependency management eliminates this waste.

Deprecation and Versioning

Block deprecation is one of the hardest problems in WordPress block development, and a registry makes it manageable. When you need to change a block’s markup, attributes, or save function, WordPress requires a deprecation entry that describes the old format and provides a migration path. Without centralized management, deprecations accumulate in individual block files and become difficult to track.

The registry can maintain a deprecation history for each block, automatically loading the appropriate deprecated versions when WordPress encounters old content. It can also provide tooling to identify which pages contain deprecated block versions, enabling proactive migration rather than waiting for users to encounter block validation errors.

Version tracking per block also enables A/B testing of block variations. A new version of a hero block can be deployed to a subset of editors while the stable version remains the default. The registry controls which version each editor sees based on configured rules.

When You Need a Registry

Not every project needs this level of infrastructure. A theme with 5 custom blocks does not need a registry. A plugin that adds a single block definitely does not. The complexity of a registry system is justified when:

  • Your block library exceeds 20-30 blocks
  • Multiple developers or teams contribute blocks to the same project
  • You need conditional block availability based on context, role, or post type
  • Editor performance has become noticeably slow
  • Block maintenance and consistency are consuming significant development time
  • You are building a block library that ships as a product (theme or plugin)

For projects below these thresholds, WordPress’s built-in block registration works fine. The overhead of a registry is not worth it for small block counts. But for projects that are growing toward these thresholds, planning for a registry early is much easier than retrofitting one after the block library has already become difficult to manage.

The Future of Block Management

WordPress core is slowly moving toward better block management. The block directory, block collections API, and recent improvements to the inserter’s search and filtering capabilities are steps in the right direction. But the pace of core development is conservative, and the needs of large block libraries are outpacing what core provides.

The registry pattern fills the gap between what WordPress provides out of the box and what production block themes and plugins actually need. It is the same architectural pattern that every large frontend framework eventually adopts: a centralized system for managing component registration, loading, and organization.

WordPress blocks are components. Treat them like components. Register them through a system that scales, loads them when they are needed, organizes them so users can find them, and maintains them so your team can work on them without stepping on each other. That is what a registry gives you. And when your block library hits 50+, you will be glad you built one.

Scroll to Top