Every product attribute has a running cost
Magento's attribute system is flexible by design, and that flexibility has a price that grows quietly. Every custom attribute you add makes reads, writes, and indexing a little more expensive, on every product, forever.
On a store that has run for years, unused and over-configured attributes accumulate into real catalog slowness. Product saves crawl, reindexing takes longer, and category pages get heavier, all without a single obvious cause.
This article covers how the EAV model stores product data, where the cost lands on reads and writes and indexing, how to measure your attribute footprint, and how to reduce the debt.
How EAV stores product data
Magento uses the entity-attribute-value model for products. Instead of one wide table, product data is spread across a set of tables by data type: catalog_product_entity_varchar, _int, _decimal, _text, and _datetime.
Each attribute value for each product is a separate row in one of those tables. A product with fifty populated attributes is not one row, it is one entity row plus dozens of value rows scattered across several tables.
This is what makes Magento flexible enough to model any catalog. It is also what makes attribute count a direct multiplier on how much work the database does for every product operation.
The cost of reading many attributes
Reading a product means gathering its values from all those tables. Loading several attributes means several joins, or several row lookups, to reassemble one product.
The classic mistake amplifies this. Calling addAttributeToSelect('*') on a collection tells Magento to load every attribute for every product, which pulls a large number of rows to build objects that often only need a few fields.
addAttributeToSelect('*') turns a small read into a large one, every time the code runs.The cost of writing a product
Saving a product is not one write. It is a fan-out across every attribute-backing table that holds a value for that product.
Each changed attribute updates its row in the relevant type table, and a full product save touches many of them. When an import updates thousands of products, that fan-out multiplies into an enormous number of individual writes.
This is why bulk product operations get slower as attribute count grows. The per-product cost is small, but it is paid on every attribute, on every product, on every save.
Attributes you forgot you have
The debt is rarely from attributes in active use. It is from the ones added over years, for a feature or an integration, and never removed when they stopped being needed.
Each of those still participates in reads, writes, and indexing. An unused attribute is not free just because nothing displays it, because Magento still carries it through every product operation.
The eav_attribute table holds every attribute defined for the store. On a mature catalog, a large fraction of the product attributes there turn out to be legacy that nobody has touched in years.
Filterable and searchable attributes multiply index work
Two attribute settings quietly add the most cost. An attribute marked filterable feeds the layered navigation index, and one marked searchable feeds the search index.
Every filterable attribute adds rows to catalog_product_index_eav, the index behind layered navigation. The more filterable attributes you have, and the more values each has, the larger that index grows and the longer it takes to rebuild.
Searchable attributes add to the search engine index in the same way. An attribute set to searchable or filterable "because it might be useful" is a standing cost on every reindex, whether or not customers ever filter on it.
The layered navigation index specifically
The layered navigation index deserves its own attention, because it grows multiplicatively. Its size is roughly the number of filterable attributes times the number of values times the number of products they apply to.
A store that made a dozen attributes filterable, each with many values, across a large catalog, builds a very large catalog_product_index_eav table. That table has to be rebuilt on reindex and read on category pages.
This is a frequent finding on slow category pages. The layered navigation is doing far more work than the store's actual filtering needs, because filterable was turned on broadly and never reviewed.
Indexing time scales with attributes
Reindexing is where attribute debt becomes visible operationally. The catalog and price indexers read the EAV data and build the flat index tables the storefront uses.
More attributes mean more data to read and more index rows to write. A reindex that took minutes on a lean catalog can take much longer once years of attributes have accumulated, and that time affects how current the storefront data stays.
Reindex time climbs with attribute count, and filterable attributes drive the steepest part of the curve.
Import and export cost
Catalog import and export scale with attribute count as directly as saves do. Each row of an import has to be mapped and written across the attribute tables, and each row of an export has to be gathered from them.
A store with a bloated attribute set finds its imports slow and its exports heavy, even for the same number of products. The width of the data, not just the number of products, drives the cost.
Integrations that push catalog updates frequently feel this most. Every sync pays the attribute tax, and a leaner attribute set makes every sync faster.
Static versus EAV backend types
Not every attribute has to live in the EAV tables. Attributes with a backend type of static are stored as columns on the main entity table instead of as separate value rows.
Core attributes that are read constantly, like SKU, use static storage for exactly this reason. It trades the flexibility of EAV for the speed of a single-table read.
For custom attributes that are read on nearly every product and never need EAV's flexibility, static storage can be the right choice. It is a design decision worth making deliberately rather than defaulting everything to EAV.
The history of flat catalog
Older Magento versions offered a flat catalog option, which merged EAV data into wide flat tables for faster reads. It was a common performance recommendation for years.
Recent Magento has deprecated and moved away from flat catalog, relying on the index tables instead. If your store still has flat catalog enabled from an older era, it is worth confirming whether it is still appropriate for your version.
The lesson from flat catalog stands regardless: EAV reads are expensive enough that Magento has always needed a denormalized layer on top for the storefront. Reducing attribute count reduces the work that layer has to do.
Attribute sets and where attributes apply
Attributes are grouped into attribute sets, and a product uses the attributes in its set. This is meant to keep products lean, applying only the attributes each product type needs.
In practice, attribute sets bloat too. Attributes get added to the default set out of convenience, so they apply to products that never use them, and every one of those products now carries the cost.
Reviewing which attributes belong to which set is part of controlling the debt. An attribute that only a handful of products need should not sit in the set that every product inherits.
Dropdown attributes and their option tables
Dropdown and multiselect attributes carry extra weight beyond their values. Their options live in eav_attribute_option and eav_attribute_option_value, and those tables grow with every option ever defined.
An attribute that accumulated hundreds of options over the years, many no longer used, still carries all of them. Rendering the attribute, filtering on it, and importing against it all have to account for the full option set.
Cleaning up stale options is a smaller version of cleaning up stale attributes. Both remove cost that the store pays for data nobody uses anymore.
The price index and attribute complexity
Pricing multiplies EAV complexity in its own way. The price index has to account for tier prices, special prices, catalog price rules, and per-customer-group pricing, all of which are attribute-driven.
Each pricing dimension expands what the price index must compute and store. A store with many customer groups and active catalog price rules builds a larger, slower price index, and that cost compounds with the attribute cost.
Third-party extensions add attributes too
Not all attribute debt is home-grown. Extensions frequently add their own product attributes on install, and those attributes remain even after the extension is removed if the uninstall was incomplete.
A store that has tried several extensions over the years can carry attributes from all of them, including ones whose extensions are long gone. These orphaned attributes are pure cost, since nothing even reads them anymore.
When auditing attributes, cross-reference them against the extensions still installed. Attributes tied to removed extensions are safe, high-value candidates for cleanup.
The frontend pays for attributes too
Attribute cost is not only a backend and indexing story. The storefront pays as well, on the pages customers actually load.
A product page renders its attribute values, and a product listing collection loads attributes for every product it shows. A category page with a heavy layered navigation queries the attribute index to build its filters, on every request that is not served from cache.
The more attributes involved, the more each of these does. When category and product pages feel heavy, an over-configured attribute set is often part of the reason, alongside the caching factors.
Layered navigation depth compounds it
Layered navigation is where filterable attributes turn into a visible experience, and a costly one. Each filterable attribute becomes a filter, and each filter combination is a query against the attribute index.
A navigation with many filters, each with many values, produces a large number of possible combinations. That breadth is what makes the index large and the category queries heavier, and it grows faster than the attribute count alone would suggest.
Reviewing which filters customers actually use is worthwhile. A store often exposes far more filters than shoppers ever touch, paying the index and query cost for navigation nobody uses.
A practical target: fewer, deliberate attributes
The goal is not the minimum possible attributes, it is deliberate ones. Every attribute should earn its place by being used, and every filterable or searchable flag should reflect a real customer need.
That standard, applied over time, keeps the catalog lean without a dramatic cleanup. New attributes get added with intent, and old ones get reviewed rather than accumulating by default.
A store that treats attributes as free will always drift toward bloat. One that treats each as a standing cost keeps its catalog operations fast as it grows.
How to measure your EAV footprint
The debt is measurable with a few queries. Start by counting the product attributes and how many are configured for indexing:
SELECT COUNT(*) AS product_attributes
FROM eav_attribute a
JOIN eav_entity_type e ON e.entity_type_id = a.entity_type_id
WHERE e.entity_type_code = 'catalog_product';
SELECT COUNT(*) AS filterable
FROM catalog_eav_attribute
WHERE is_filterable > 0;
Then check the size of the index tables those attributes feed, especially catalog_product_index_eav, using the sizing query against information_schema. A large index relative to the catalog size points straight at over-configured filterable attributes.
Cross-reference the attribute list against what the storefront actually uses. Attributes that are filterable or searchable but never appear in navigation or search results are pure cost.
Cross-referencing indexed attributes against actual storefront use exposes the ones that are pure cost.
Media and gallery attributes add their own rows
Product images are attribute-adjacent debt worth noting. Media is stored in its own gallery tables rather than the simple value tables, and each image on each product is another row to manage.
A catalog where products carry many images, including ones no longer used, accumulates gallery rows the same way attributes accumulate values. Imports and product saves have to account for all of them.
Cleaning up unused images is a smaller companion to attribute cleanup. It reduces the per-product weight of media the same way removing attributes reduces the weight of data.
Reducing the debt
Reduction is careful work, because attributes can hold data you do not want to lose. The safe order is to review before you remove.
Turn off filterable and searchable on attributes the storefront does not use for either, which shrinks the index without touching data. Then identify attributes that are genuinely unused and remove them, testing on a copy first because removal deletes their values.
Where a heavily read custom attribute never needs EAV flexibility, consider whether static storage suits it better. Each of these changes reduces the per-product cost that every catalog operation pays.
Removing an attribute safely
Removing an attribute deletes its values, so it is not a change to make casually. The safe path is a data patch that uses the EAV setup to remove the attribute cleanly, tracked in code rather than run by hand.
Test the removal on a copy of production first, and confirm that nothing on the storefront, in an import mapping, or in a report depends on the attribute. An attribute that looks unused can still be referenced by a custom template or an integration that will break when it disappears.
Doing it as a versioned data patch means the removal is repeatable across environments and recorded in history. That is the difference between a controlled cleanup and a surprise when the next environment does not match.
Lean catalogs stay fast
Attribute debt is invisible day to day and expensive in aggregate. It shows up as slow saves, long reindexes, heavy category pages, and sluggish imports, none of which point obviously at attribute count.
The reward for keeping it lean compounds. Faster saves speed up imports, shorter reindexes keep storefront data fresh, and lighter category pages improve the experience customers actually see, all from the same underlying discipline.
Knowing how many attributes you carry, how many are needlessly indexed, and how many are unused turns that invisible drag into a concrete reduction plan. Measuring the EAV footprint is one of the highest-value checks in a catalog performance review.