← IT Knowledge Base Home

Magento / Adobe Commerce — Fundamentos, Arquitectura, EAV, DI y Plugins, Layout, Funcionalidad de Comercio, Rendimiento, APIs, Seguridad y Administración

Pregunta de origen (entrevista / cuestionario): ¿Cuál es su experiencia con Magento (Adobe Commerce) en configuración funcional, desarrollo de módulos y storefront, integraciones, seguridad y administración?

Esta página cubre 10 bloques del temario: fundamentos, ediciones y versiones (Q1–Q8), arquitectura técnica (Q9–Q16), módulos, Composer y ciclo de despliegue (Q17–Q25), modelo de datos y EAV (Q26–Q34), inyección de dependencias, plugins y eventos (Q35–Q43), frontend: layout, temas y storefront (Q44–Q52), funcionalidad de comercio (Q53–Q61), rendimiento, indexación y caché (Q62–Q69), integraciones y APIs (Q70–Q77) y seguridad, multi-store, calidad y administración (Q78–Q85), más una plantilla de respuesta para entrevista y referencias.

Contenido

1. Fundamentos, ediciones y versiones

Q1. ¿Qué es Magento / Adobe Commerce y para qué se usa?

Magento es una plataforma de comercio electrónico open source escrita en PHP sobre MySQL/MariaDB, hoy producto de Adobe: la edición gratuita se llama Magento Open Source y la de pago Adobe Commerce (con variante gestionada Adobe Commerce Cloud). Se usa para tiendas B2C y B2B de tamaño medio y grande que necesitan catálogos extensos, reglas de precio y promoción complejas, multi-tienda/multi-país/multi-moneda, checkout personalizable e integraciones profundas con ERP, PIM, OMS y medios de pago. Su fortaleza es la flexibilidad: casi todo es extensible sin modificar el core, gracias a la inyección de dependencias, plugins, eventos y layout XML. Su costo es la complejidad: requiere equipo técnico y una infraestructura bien dimensionada.

Q2. ¿Cuál es la historia y evolución de la plataforma?

Magento nació en Varien y su primera versión estable se publicó en 2008; eBay la adquirió en 2011 y en 2015 pasó a Permira, momento en el que se lanzó Magento 2 (2.0, noviembre de 2015): reescritura completa con DI, plugins, composer, nuevos patrones de frontend y stack moderno. Magento 1 llegó a su fin de soporte en junio de 2020. En 2018 Adobe compró la compaña y renombró las ediciones: Magento Community → Magento Open Source, Magento Commerce → Adobe Commerce, y Magento Commerce Cloud → Adobe Commerce Cloud. Desde entonces la plataforma se integra con el ecosistema Adobe (Experience Manager, Analytics, Target, Journey Optimizer) y con servicios como Live Search y Product Recommendations.

Q3. ¿Qué diferencias hay entre Magento Open Source, Adobe Commerce y Adobe Commerce Cloud?

La decisión depende del presupuesto, de la necesidad de B2B/merchandising avanzado y de si el equipo quiere operar la infraestructura.

Q4. ¿Qué aporta el módulo B2B de Adobe Commerce?

El conjunto B2B (módulos Magento_* de la suite B2B) cubre: Company accounts con estructura jerárquica de usuarios y roles, Shared Catalogs (catálogo y precios específicos por empresa), Quotes (negociación de cotizaciones entre comprador y vendedor con historial), Requisition Lists (listas de recompra), Quick Order por SKU/CSV, credit limits y pago a crédito (Purchase Order), aprobaciones internas, y gestión de precios por volumen (tier prices). También se apoya en atributos de cliente, grupos de clientes y reglas de impuestos/envío por empresa. En proyectos B2B conviene validar desde el inicio estos flujos porque condicionan el modelo de datos, las integraciones con el ERP (crédito, precios contractuales) y la experiencia de checkout.

Q5. ¿Cómo es el ciclo de versiones y de parches? ¿Qué se debe tener en cuenta?

Adobe publica la línea 2.4.x con releases funcionales (típicamente dos al año) y parches de seguridad y de calidad entre medias; cada versión 2.4.x recibe soporte por un periodo definido y después solo parches de calidad/seguridad durante una ventana adicional. Puntos prácticos: verificar la versión soportada vigente y su fecha de fin de soporte antes de iniciar un proyecto; los parches se aplican con el paquete magento/quality-patches (o magento/magento-cloud-components en Cloud) declarándolos en el Composer; y los cambios de requisitos de PHP/OpenSearch por versión obligan a actualizar el stack. Planificar el upgrade anual o bianual es parte del costo total de propiedad: dejar la plataforma sin soporte implica riesgo de seguridad y de compatibilidad con extensiones.

Q6. ¿Qué requisitos de infraestructura tiene Magento 2?

Q7. ¿Cómo se compara con otras plataformas de eCommerce?

Q8. ¿Cómo es el ecosistema Magento (Marketplace, partners, comunidad)?

El ecosistema incluye: Adobe Commerce Marketplace (extensiones y temas certificados, con revisión de código y compatibilidad), partners de implementación (Solution Partners certificados, con niveles), desarrolladores certificados (Adobe Certified Professional / Expert - Commerce Developer), Magento Open Source Project Governance y la comunidad (foros, Slack, meetups, Magento Stack Exchange, Magento DevBlog), y Packagist para paquetes Composer. Buenas prácticas al elegir extensiones: verificar compatibilidad con la versión, reputación del vendor, soporte y actualizaciones, impacto en rendimiento, calidad del código (idealmente disponible para revisar) y licencia. Cada extensión es deuda de mantenimiento en cada upgrade, por lo que conviene preferir el estándar cuando cubre el requisito.

2. Arquitectura técnica

Q9. ¿Cómo está estructurada la arquitectura de Magento 2 por capas?

De abajo hacia arriba: Persistence layer (MySQL + modelos, resource models, colecciones y EAV), Domain layer (lógica de negocio en los modelos y en las clases de dominio, sin dependencia de la presentación), Service layer (Service Contracts: interfaces Api + Api/Data, expuestas como Web API REST/SOAP/GraphQL y usadas internamente), Presentation layer (bloques, ViewModels, templates, layout XML, UI Components del admin) y, transversal, la capa de infraestructura (DI container, plugins, eventos, cache, indexers, colas). El principio rector es la extensibilidad: en lugar de modificar el core se interviene con preferencias, plugins, eventos, layout y temas, y todo se resuelve en tiempo de compilación (setup:di:compile) generando interceptors y la configuración de DI.

Q10. ¿Cuál es la estructura de directorios del proyecto?

Q11. ¿Qué modos de despliegue existen y en qué se diferencian?

Se cambia con bin/magento deploy:mode:set production (o developer). Además, MAGE_MODE puede fijarse por entorno. Un error clásico es desplegar en production sin recompilar DI y sin regenerar estáticos, lo que produce pantallas rotas o 500.

Q12. ¿Qué es el Object Manager y por qué se considera un anti-patrón usarlo directamente?

El Object Manager es el contenedor de DI de Magento: lee la configuración de di.xml (global, por área y por módulo), resuelve constructores, aplica preferencias, argumentos, plugins y tipos virtuales, y crea proxies/factories. Usarlo directamente ($this->_objectManager->get(...)) es un anti-patrón porque: oculta las dependencias reales de la clase (rompe el principio de dependencias explícitas), impide probar con dobles/mock, hace imposible detectar errores en setup:di:compile y dificulta que plugins/preferencias se apliquen correctamente. La forma correcta es inyección por constructor (con Factory para objetos dinámicos) y, cuando la dependencia es opcional o circular, usar interfaces y virtualType. Solo hay contextos muy concretos donde el framework lo requiere (por ejemplo, algunas clases legacy del core).

Q13. ¿Qué son los Service Contracts y por qué importan?

Un Service Contract es un contrato público y estable formado por interfaces Vendor\Module\Api\* (operaciones: save, get, getList, delete) e interfaces de datos Vendor\Module\Api\Data\*Interface (getters/setters), implementadas por los Repository. Ventajas: desacoplan a los consumidores de la implementación interna (el core puede cambiar tablas o lógica sin romper integraciones), se exponen automáticamente como Web API declarando la ruta en webapi.xml, permiten cachear y versionar el contrato, y facilitan pruebas. En desarrollo custom conviene definir service contracts para todo lo que consuma otra capa (frontend, integraciones, módulos de terceros) y usar SearchCriteria en los métodos getList, que es el estándar de consulta en Magento 2.

Q14. ¿Cómo funciona el flujo de una petición HTTP?

pub/index.php arranca la aplicación (bootstrap, área, modo), el front controller recibe la petición y la pasa por la cadena de routers: el router estándar resuelve routeId/controller/action contra routes.xml y las clases Controller\...\Index; existen routers adicionales (URL rewrite, diseño, admin). El controller ejecuta la lógica mínima y devuelve un objeto Result (ResultInterface: page con layout, json, redirect, forward, raw). Si es una página, el layout se construye a partir de los handles (por ejemplo default, catalog_product_view, checkout_index_index), se crean los bloques/ViewModels, se renderizan los templates PHTML y se aplican los wrappers. Antes de responder actúan los plugins, y el resultado puede guardarse en full page cache. Las peticiones de admin usan el área adminhtml con su propia configuración y validación de CSRF/ACL.

Q15. ¿Cómo funciona la configuración por scopes y cómo se resuelve?

Magento tiene una jerarquía de scopes: global (default) → website → store → store view. Cada parámetro de configuración se declara en etc/config.xml (valores por defecto) y etc/adminhtml/system.xml (campos del admin con su scope permitido), y se guarda en core_config_data con scope y scope_id. Se lee con ScopeConfigInterface::getValue('seccion/grupo/campo', ScopeInterface::SCOPE_STORE, $storeId), que hace fallback hacia arriba si no hay valor en el scope pedido. Implicaciones prácticas: precios, impuestos, métodos de envío/pago y contenido suelen configurarse a nivel website o store view; atributos de producto pueden ser globales o por store view (por ejemplo, nombre y descripción traducidos); y los índices y cachés deben considerar el scope para no servir contenido equivocado entre tiendas.

Q16. ¿Cómo se gestiona la configuración entre entornos (config.php, env.php, app:config:import)?

Tres piezas distintas: env.php guarda credenciales, caché/sesiones, crypt key y opciones de entorno — nunca se versiona y se inyecta por entorno (variables de entorno en Cloud). config.php lista los módulos y su estado (activado/desactivado) y, cuando se exporta con bin/magento app:config:export, incluye la configuración compartida de tiendas/scopes y themes; sí se versiona para que los despliegues sean reproducibles. core_config_data guarda los valores del admin: los que se marcan como «compartidos» se exportan a config.php y el resto se gestiona por entorno (o con config:set / scripts). En el despliegue se ejecuta app:config:import (automático en el pipeline) para aplicar el estado exportado, evitando sobreescribir valores específicos de producción. Esta separación es clave para pasar de dev a staging a producción sin romper la configuración.

3. Módulos, Composer y ciclo de despliegue

Q17. ¿Cuál es la estructura de un módulo Magento 2?

Un módulo se identifica como Vendor_Module y vive en app/code/Vendor/Module o en vendor/ si se distribuye por Composer. Estructura típica: registration.php, composer.json, etc/ (module.xml, di.xml, config.xml, events.xml, crontab.xml, indexer.xml, db_schema.xml, webapi.xml, acl.xml, adminhtml/system.xml, frontend/routes.xml, adminhtml/routes.xml, view/), Api/ y Api/Data/ (contratos), Model/ (dominio, repositorios, resource models), Controller/ (acciones frontend/admin), Block/ y ViewModel/, Observer/, Plugin/, Setup/Patch/, Console/, view/frontend y view/adminhtml (templates, layout, web/js, web/css, i18n), Test/ y i18n/. La separación por áreas (frontend/adminhtml/webapi) permite cargar configuración distinta según el contexto de la petición.

Q18. ¿Qué declaran registration.php, module.xml y composer.json?

Un sequence mal declarado produce errores de instalación o de DI; es uno de los primeros puntos a revisar cuando un módulo falla al activarse.

Q19. ¿Cómo se gestiona el orden de carga y las dependencias entre módulos?

Magento construye un grafo con: dependencias Composer (paquetes requeridos), secuencias declaradas en module.xml y el orden de carga de configuración. Cada área (global, frontend, adminhtml, webapi, crontab) tiene su propio di.xml y sus events.xml, y la configuración se fusiona entre módulos: por eso un plugin o una preferencia declarada en tu módulo afecta a todas las clases del área correspondiente. El orden de los plugins se controla con sortOrder, no con el orden de carga. Buenas prácticas: declarar el mínimo de dependencias (si solo necesitas una interfaz, no dependas del módulo completo), usar sequence solo cuando sea imprescindible y comprobar el resultado con bin/magento module:status y setup:di:compile, que detecta ciclos y clases inexistentes.

Q20. ¿Cómo se instala, habilita, deshabilita y actualiza un módulo?

Flujo estándar: instalar el paquete con Composer (composer require vendor/module) o colocar el código en app/code; luego bin/magento module:status Vendor_Module para verlo, module:enable (modifica app/etc/config.php), y ejecutar el despliegue de esquema/datos: en 2.4.x se usa bin/magento setup:upgrade (que aplica db_schema.xml y los parches de datos) o, en pipelines modernos, setup:db-declaration:generate-whitelist + declarative schema; después setup:di:compile (production), setup:static-content:deploy, cache:clean y reindexar si hace falta. Para desactivar: module:disable + setup:upgrade + recompilar; la desinstalación real (module:uninstall) solo funciona con módulos que traen esquema de desinstalación y requiere cuidado porque puede borrar tablas y datos. En producción todo esto se automatiza en el pipeline, no a mano.

Q21. ¿Qué comandos CLI son esenciales?

Q22. ¿Qué es el declarative schema y cómo se aplican los parches de datos?

Desde 2.3 el esquema de base de datos se declara en db_schema.xml (tablas, columnas, índices, constraints, claves foráneas), y Magento calcula la diferencia con el esquema real y lo aplica de forma idempóntica, reemplazando los antiguos InstallSchema/UpgradeSchema. Para cambios de datos se usan Data Patches (Setup/Patch/Data/ClasePatch.php implementando DataPatchInterface con apply() y getAliases()), registrados en patch_list para no ejecutarse dos veces. Además existe el whitelist (db_schema_whitelist.json) que controla qué elementos puede eliminar el schema declarativo (protege tablas/columnas creadas por otros módulos o por upgrades). Buenas prácticas: parches atómicos y reversibles, sin lógica de negocio pesada, y probados en staging con datos reales.

Q23. ¿Cómo se maneja Composer y cómo se aplican los parches de calidad?

El proyecto se instala desde el metapaquete Composer (magento/product-community-edition o magento/product-enterprise-edition) con las claves de acceso del repositorio de Adobe (repo.magento.com). La estructura recomendada es Magento Cloud / composer-based: el código del core en vendor/, los módulos propios como paquetes Composer en repositorios privados (mejor que app/code para proyectos grandes) y un composer.lock versionado para garantizar reproducibilidad. Los parches se aplican con magento/quality-patches (plugin de Composer) listándolos en composer.json bajo extra → magento-quality-patches, o con parches propios vía cweagans/composer-patches. Conviene documentar cada parche aplicado (motivo, ticket, versión en la que queda incorporado) para poder retirarlo tras el upgrade.

Q24. ¿Cómo se despliega en producción con el menor riesgo?

Pipeline típico: (1) build de artefactos con composer install --no-dev; (2) setup:di:compile (genera interceptors y config compilada); (3) setup:static-content:deploy por locales y temas (-f, con --jobs para paralelizar); (4) setup:upgrade / aplicación de esquema y parches de datos; (5) app:config:import; (6) cache:flush y reindexado (idealmente con indexers en modo schedule y reindexado en un proceso aparte); (7) verificación de humo (checkout de prueba, búsqueda, admin). Cero downtime: en infraestructura propia se despliega en un directorio nuevo y se cambia el symlink de la docroot; en Cloud se hace blue/green por entorno. Imprescindible: backup/snapshot previo, plan de rollback (código + base de datos), ventana comunicada y evitar reindexados pesados en horas pico.

Q25. ¿Cómo se organiza el repositorio y el CI/CD en un proyecto Magento?

Opciones habituales: (a) repositorio único del proyecto con composer.json + módulos propios en app/code (simple, rápido para equipos pequeños); (b) módulos propios como paquetes Composer privados versionados por separado (mejor aislamiento, reutilización entre proyectos y control de versiones, requiere registry privado y disciplina de release); (c) en Adobe Commerce Cloud, repositorio Git conectado a la plataforma con ramas por entorno y despliegue automático con ece-tools. El pipeline debe ejecutar: instalación de dependencias, tests estáticos (PHP_CodeSniffer con magento/magento-coding-standard, PHPMD, PHP compatibility), unitarios y de integración, MFTF para flujos críticos, build de estáticos y despliegue a staging con smoke tests. Ramas: feature → develop → release/staging → main/production, con revisión por pares y composer.lock siempre versionado.

4. Modelo de datos y EAV

Q26. ¿Qué es EAV y cómo se estructura en Magento?

EAV (Entity-Attribute-Value) es el modelo que permite añadir atributos desde el admin sin alterar el esquema. Por cada entidad EAV hay una tabla base (catalog_product_entity, customer_entity, sales_order no es EAV) y tablas de valores por tipo de dato: *_entity_varchar, *_entity_int, *_entity_decimal, *_entity_text, *_entity_datetime. La definición vive en eav_entity_type, eav_attribute (código, backend_type, source_model, frontend_input, is_required, scope), eav_attribute_set, eav_attribute_group y eav_attribute_option/_value para las opciones. Cada fila de valor lleva entity_id, attribute_id y store_id, lo que da soporte nativo a valores por store view. Entender este modelo explica tanto la flexibilidad de Magento como su costo en consultas.

Q27. ¿Qué tipos de atributos, backend types y attribute sets existen?

Los backend types (donde se guarda el valor) son varchar, int, decimal, text, datetime, static; static guarda el valor en la tabla base de la entidad (mejor rendimiento, usado por ejemplo en SKU). Los frontend inputs (cómo se captura) incluyen text, textarea, date, boolean, multiselect, select, price, media_image, gallery, swatch_visual, swatch_text, y tipos específicos como tier price o weee. Los attribute sets agrupan atributos en grupos y se asignan por producto: definen qué atributos existen para cada tipo de producto (los atributos de sistema como sku, price, status, visibility son obligatorios). El scope del atributo puede ser global, website o store view. Un atributo custom se crea en el admin o por db_schema/data patch con AttributeManagement, y para usarlo en listados/búsqueda hay que marcarlo como used_in_product_listing y searchable/filterable, lo que implica reindexado.

Q28. ¿Por qué EAV es flexible pero lento, y cómo se mitiga?

Leer un producto con 100 atributos exige unir decenas de filas en varias tablas (una por backend type y por store view, con fallback), lo que genera consultas grandes y poco cacheables. Mitigaciones: (1) indexadores que materializan datos planos para listados y precios (catalog_product_index_eav, catalog_product_index_price); (2) Elasticsearch/OpenSearch, que desde 2.4 asume las consultas de catálogo y búsqueda (los atributos se indexan como campos del documento, evitando joins en runtime); (3) caché de colecciones y de EAV (eav, collections, full_page); (4) cargar solo los atributos necesarios (addAttributeToSelect con campos específicos, no '*'); (5) usar static para atributos muy consultados y (6) tablas planas propias para integraciones/reportes. La regla: EAV para flexibilidad de administración; índices y buscador para rendimiento de lectura.

Q29. ¿Qué pasó con el flat catalog y qué alternativas hay?

Magento 1 y las primeras versiones de Magento 2 tenían la opción de catálogo plano (tablas catalog_product_flat) para acelerar listados. Fue deprecado y eliminado en la línea 2.3/2.4 porque era incompatible con las nuevas arquitecturas de búsqueda, generaba tablas enormes con muchos atributos y complicaba el reindexado. Desde 2.4 la búsqueda y los listados se resuelven con Elasticsearch/OpenSearch, y los precios/atributos filtrables con indexadores propios. Si un proyecto necesita lecturas masivas planas (feeds, integraciones, BI), la práctica correcta es generar tablas o vistas propias alimentadas por indexadores/observadores o extraer los datos con la API/GraphQL, sin reactivar mecanismos obsoletos.

Q30. ¿Cómo se trabaja con modelos, resource models y colecciones?

Patrón clásico: Model (extends \Magento\Framework\Model\AbstractModel, con _init(ResourceModel)), ResourceModel (extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb, define _init('tabla','pk') y consultas SQL) y Collection (extends \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection). Para entidades EAV se usan las variantes AbstractEntity/Entity\AbstractCollection con addAttributeToSelect/Filter/Sort. Desde Magento 2 se recomienda exponer Repositorios con SearchCriteria en lugar de usar colecciones directamente fuera del modelo, porque las colecciones acoplan la lógica a SQL y no funcionan tras los service contracts ni en APIs. Para consultas complejas (reportes, feeds) sigue siendo legítimo usar ResourceConnection con Select del framework (nunca concatenar SQL sin escapar) o vistas de base de datos.

Q31. ¿Qué tipos de producto existen y cómo se modelan?

Cada tipo tiene su type_id, clases Product\Type\* con lógica de precio/peso/preparación para el carrito, y tablas específicas. Elegir el tipo correcto impacta en inventario, precios, envío e integraciones con el ERP.

Q32. ¿Cómo funcionan las categorías, la navegación por capas y el posicionamiento?

Las categorías (catalog_category_entity, EAV) forman un árbol con path, level, position y include_in_menu; cada categoría tiene display_mode (productos, bloque CMS o ambos), reglas de visualización y anchors. La relación producto-categoría está en catalog_category_product y su índice en catalog_category_product_index. La navegación por capas (layered navigation) usa los atributos marcados como filterable con sus índices EAV (catalog_product_index_eav) y el motor de búsqueda para calcular los conteos por faceta; en Adobe Commerce, Live Search mejora relevancia y facetas con servicios de Adobe. El orden dentro de la categoría se controla con position, reglas de producto (Visual Merchandiser en Commerce) y la configuración de orden por precio/nombre/novedad. Cambios en categorías requieren reindexar para reflejarse en frontend.

Q33. ¿Cómo se modelan clientes, direcciones y sus atributos?

El cliente es una entidad EAV (customer_entity + tablas de valores) con direcciones en customer_address_entity (también EAV). Se organizan por grupos de clientes (que afectan precios, impuestos y reglas de carrito) y por website (un cliente pertenece a un website, clave en multi-tienda). Los atributos custom se crean en el admin o por patch y pueden marcarse como visibles en registro, cuenta, checkout o admin, con validación (input_validation) y reglas por store view. Adobe Commerce añade Customer Attributes (atributos gestionables por el merchandiser), segmentación (segmentos dinámicos por comportamiento/datos usados para promociones y contenido) y RMA. Consideraciones: contraseñas hasheadas con el mecanismo nativo (Argon2ID en versiones recientes), cumplimiento de GDPR (exportación/borrado y anonimizado), y cuidado con la cache de páginas con contenido de cliente (agujeros de FPC).

Q34. ¿Qué son los extension attributes y cuándo usarlos?

Los extension attributes permiten añadir campos a los contratos de datos del core (Api\Data\*Interface) sin modificarlos: se declaran en etc/extension_attributes.xml indicando la interfaz base, el código y el tipo (type="string", type="Magento\Catalog\Api\Data\ProductInterface[]", etc.), y se acceden con getExtensionAttributes()/setExtensionAttributes(). Se usan típicamente para exponer datos adicionales en las Web API (por ejemplo, información de inventario MSI en el quote, o campos custom en el order) y en plugins sobre afterGetList/afterGet para poblarlos. A diferencia de los atributos EAV (visibles para el usuario en el admin y configurables), los extension attributes son estructurales y viven en el contrato técnico: se usan para datos que no deben gestionarse por el administrador de la tienda, y para mantener la compatibilidad de las APIs.

5. Inyección de dependencias, plugins y eventos

Q35. ¿Cómo funciona la inyección de dependencias y di.xml?

El contenedor resuelve las dependencias del constructor leyendo la configuración acumulada de di.xml (global en app/etc, por módulo en etc/, y por área en etc/frontend o etc/adminhtml). Etiquetas principales: <preference> (asocia una interfaz a una implementación), <type> + <arguments> (injecta valores o cambia argumentos de un constructor), <virtualType> (crea un «alias» de una clase con argumentos distintos sin duplicar código, muy usado en bloques, colecciones y fuentes de datos del admin), <plugin> (interceptores), <arguments> con xsi:type (object, string, boolean, number, array, const, null, init_parameter). En setup:di:compile se genera el código compilado (generated/code) con factories, proxies e interceptors, y se validan errores de resolución. Preferencias y plugins deben usarse con criterio: cada uno añade complejidad al grafo y al debugging.

Q36. ¿Qué son las factories, los proxies y los virtual types?

Conocer estos tres mecanismos evita escribir clases duplicadas «solo para cambiar un argumento», una de las causas más comunes de código inflado en proyectos Magento.

Q37. ¿Qué es una preference y cuándo usarla frente a un plugin?

Una preference reemplaza globalmente una interfaz o clase por tu implementación: <preference for="Magento\Catalog\Api\ProductRepositoryInterface" type="Vendor\Module\Model\ProductRepository"/>. Tu clase suele extender la original y llamar a parent::. Ventajas: control total del comportamiento. Riesgos: solo puede haber una resolución efectiva por interfaz en cada área, y si dos módulos declaran preferencias distintas se rompe la composición (el último gana), lo que genera conflictos difíciles de depurar y problemas en upgrades. Un plugin en cambio intercepta un método concreto y convive con otros plugins (encadenados por sortOrder). Regla práctica: plugin para modificar o ampliar el comportamiento de un método existente; preferencia solo cuando necesitas sustituir toda la implementación (y documentarlo), nunca para añadir un campo o un paso adicional.

Q38. ¿Cómo funcionan los plugins y cuáles son sus limitaciones?

Un plugin intercepta llamadas a métodos públicos de clases instanciadas por el contenedor DI, con tres tipos: before (modifica argumentos antes de la llamada, devuelve array de args), after (modifica el resultado o ejecuta efectos tras la llamada, recibe $result) y around (envuelve la llamada y decide si/ejecutar $proceed; el más potente y el más costoso). Se declaran en di.xml con <plugin name="..." type="Clase" sortOrder="10" disabled="false"/> y se implementan como beforeMetodo/afterMetodo/aroundMetodo. Limitaciones: no interceptan métodos no públicos, final, estáticos, métodos mágicos (__call, __get), el constructor, ni objetos creados con new o por el Object Manager fuera del flujo de DI. También hay que evitar efectos laterales en after sobre objetos que no se devuelven, y no usar around cuando basta con before/after (rompe la cadena si no se llama a $proceed).

Q39. ¿Cómo se ordenan los plugins y cómo se depuran los conflictos?

El orden lo fija sortOrder dentro de di.xml (menor = más externo en around, y el orden de ejecución en before/after); los plugins de distintos módulos sobre el mismo método se encadenan formando una «cebolla». Para depurar: (1) revisar la configuración compilada en generated/code/.../Interceptor.php y en var/di/app/etc (o ejecutar setup:di:compile y mirar el orden resultante); (2) listar los plugins que afectan a una clase con el profiler o con herramientas como el plugin debugger de extensiones conocidas; (3) usar disabled="true" para desactivar selectivamente y aislar el culpable; (4) evitar plugins sobre métodos muy calientes (getPrice, toHtml, afterGetList en repositorios) porque multiplican el costo por registro; (5) documentar los plugins propios con su intención. Los conflictos típicos: dos módulos que modifican el mismo resultado (por ejemplo, precio o stock) y dependen de ejecutarse en un orden que nadie declaró.

Q40. ¿Cómo funcionan los eventos y observadores? ¿Cuándo conviene usarlos?

Magento despacha eventos con EventManager::dispatch('nombre_evento', ['objeto' => $objeto]); los observadores se declaran en etc/events.xml (global), etc/frontend/events.xml o etc/adminhtml/events.xml con el nombre del evento, la instancia y opcionalmente disabled. El observador implementa ObserverInterface::execute(Observer $observer) y obtiene los datos con $observer->getEvent()->getData('...'). Eventos frecuentes: catalog_product_save_after, sales_order_place_after, checkout_submit_all_after, customer_login, cms_page_render_after. Cuándo usarlos: cuando el core ya publica el evento y necesitas reaccionar sin alterar el flujo principal (notificaciones, sincronizaciones, logging). Cuándo no: para modificar el resultado de un método (mejor plugin) o para lógica crítica de negocio que deba ser transaccional. Desde Magento 2 se recomienda minimizar el uso de eventos nuevos en desarrollos propios y preferir service contracts/plugins, porque los eventos dificultan el rastreo del flujo y el testing.

Q41. ¿Cómo se configuran los cron jobs y los grupos de cron?

En etc/crontab.xml se declaran trabajos con id, instance (clase con método execute), method, schedule (expresión cron o config_path para que sea configurable desde el admin) y group. Los cron groups (etc/cron_groups.xml) definen schedule_generate_every, schedule_ahead_for, schedule_lifetime, history_cleanup_every, history_success_lifetime, history_failure_lifetime y si se ejecutan en proceso paralelo o por separado (default, index, consumers, custom). El cron del sistema operativo debe invocar bin/magento cron:run cada minuto (o usar cron:install); en producción es habitual separar el grupo index (reindexadores en schedule) y consumers (colas). Buenas prácticas: trabajos idempotentes y con timeouts, monitorear la tabla cron_schedule (jobs pendientes, fallidos, atrasados), y no ejecutar tareas largas en el grupo default porque bloquean el resto.

Q42. ¿Cómo se consultan datos con repositorios y SearchCriteria?

El estándar es SearchCriteriaBuilder + repositorio: se añaden filters (addFieldToFilter('campo','valor') con condiciones eq, neq, gt, lt, like, in, from, to, null, notnull), filter groups (los grupos se combinan con AND y los filtros dentro del grupo con OR), sort orders (addSortOrder por campo y dirección) y paginación (setCurrentPage/setSetPageSize). El resultado es un SearchResultsInterface con getItems() y getTotalCount(). En Web API se traduce a parámetros searchCriteria[filter_groups][0][filters][0][field]=..., y en GraphQL a argumentos de filtro/orden/página. Ventajas: independiza la consulta de SQL, funciona igual en REST/SOAP/interno y permite cachear. Para consultas agregadas o reportes grandes, read_group-style no existe: se usa SQL del resource model o vistas, evitando cargar miles de entidades en memoria.

Q43. ¿Cómo se implementan validaciones y reglas de negocio en un módulo custom?

En capas, de más cercana al usuario a más robusta: (1) validación de entrada en formularios con validation classes del JS y reglas del admin (UI Components); (2) validación de dominio en el modelo/servicio: clases Validator inyectadas que lanzan \Magento\Framework\Exception\LocalizedException (con frases traducibles), InputException, NoSuchEntityException o CouldNotSaveException; (3) constraints de base declarados en db_schema.xml (únicos, FK, not null) como última línea; (4) rules de negocio en servicios específicos (por ejemplo, reglas de elegibilidad de una promoción) y no dispersas en bloques o controllers. Además: mantener las operaciones transaccionales (una operación = una transacción), evitar escrituras parciales, usar ValidationException con mensajes por campo cuando el consumidor es un formulario, y cubrir cada regla con tests unitarios.

6. Frontend: layout, temas y storefront

Q44. ¿Cómo funciona el sistema de layout XML?

El layout se construye por handles: cada petición activa un conjunto de handles (default para todas, más los específicos como catalog_product_view, catalog_category_view, checkout_index_index, cms_page_view, customer_account, y handles por id como catalog_product_view_id_123). Los archivos viven en view/<área>/layout/<handle>.xml de cada módulo y tema, y se fusionan por orden de módulos y temas. Dentro se declaran: containers (estructura, con label, htmlTag, htmlClass), bloques (clase + template), references (referenceContainer/referenceBlock) con acciones (<action method="...">, arguments), move y remove, y updates (<update handle="..."/>) para reutilizar definiciones. Conocer los handles y el árbol de contenedores del tema padre (Luma/Blank) es la base para posicionar cualquier elemento sin tocar PHP.

Q45. ¿Qué son los bloques y los ViewModels, y por qué se prefieren los ViewModels?

Un block es una clase PHP asociada a un template PHTML que prepara datos y los expone al render; hereda de AbstractBlock (con _toHtml, caché de bloque, identidad de cache key). Un ViewModel implementa ViewModelInterface y se inyecta en el bloque mediante arguments del layout; el template lo obtiene con $block->getViewModel() y le pide los datos. Ventajas del ViewModel: es una clase de dominio sin acoplamiento con el framework de bloques (fácil de probar con PHPUnit puro), no depende del ciclo de vida del bloque ni de su caché, permite reutilizar la misma lógica en varios templates y evita la tentación de meter consultas y lógica de negocio en el bloque o en el PHTML. Buenas prácticas: templates sin lógica (solo formato y bucles), escape de salida ($block->escapeHtml/escapeUrl/escapeHtmlAttr) y datos por ViewModel.

Q46. ¿Cómo funcionan los templates PHTML y el fallback de temas?

Los templates (.phtml) son PHP con variables $block, $escaper, $viewModel (según versión) y métodos de traducción (__('texto')). La resolución sigue un fallback: primero el tema activo, luego el tema padre, luego el módulo (view/frontend/templates). El mismo mecanismo aplica a layout, web/, i18n e imágenes (Magento_Catalog::images/... con notación Vendor_Modulo::ruta). Para sobrescribir un template basta copiarlo a tu tema respetando la ruta del módulo; para heredar sin duplicar, es mejor añadir un bloque nuevo o usar plugins/ViewModels. El exceso de overrides crea deuda: cada archivo copiado debe revisarse en cada upgrade. En frontend moderno (Hyvä o PWA) los PHTML se sustituyen por componentes propios o por datos consumidos vía GraphQL.

Q47. ¿Qué son los UI Components del admin?

Los UI Components son una capa declarativa (XML + componentes Knockout/JS) para construir grids y formularios del panel de administración: <listing> (con dataSource basado en GridDataProvider/Reporting, columnas, filtros, acciones masivas, exportación y bookmark de vistas) y <form> (fieldsets, campos tipados con validación, scope labels, y dependencia de campos con switcherConfig/dataScope). Se configuran en view/adminhtml/ui_component/*.xml y se conectan al modelo mediante virtualType de CollectionFactory o con clases DataProvider propias. Añadir una columna custom a un grid del core se hace con un XML de extensión y, si el dato no está en la colección, con un plugin al prepareItems/Collection o con una tabla de índice. Conocerlos ahorra escribir grids a mano y mantiene la consistencia visual del admin.

Q48. ¿Cómo se maneja JavaScript: RequireJS, mixins y Knockout?

El frontend clásico (tema Luma/Blank) usa RequireJS como cargador AMD: cada widget/componente es un módulo JS definido con define([...], function(){...}), inicializado desde el template con data-mage-init='{"componente":{...}}' o con <script type="text/x-magento-init">. La configuración de paths/aliases vive en requirejs-config.js del tema o módulo. Los mixins permiten extender módulos JS existentes sin sobrescribirlos (mixins: {'Magento_Checkout/js/model/quote': {...}}). El checkout y el minicart están construidos con Knockout.js y templates HTML (view/frontend/web/template), con datos inyectados por window.checkoutConfig desde un CheckoutConfigProvider. Alternativas actuales: Hyvä (Alpine.js + Tailwind, sin RequireJS/Knockout, mucho más liviano) y PWA/headless con React consumiendo GraphQL, donde el JS del core deja de usarse.

Q49. ¿Cómo se crea un tema y qué convenciones tiene?

Un tema vive en app/design/frontend/Vendor/tema con: theme.xml (nombre y <parent>, normalmente Magento/blank), registration.php, composer.json (si se distribuye como paquete, tipo magento2-theme), etc/view.xml (dimensiones de imágenes por tipo, Magento_Catalog::etc/view.xml), Magento_*/ carpetas por módulo para overrides de layout/templates/web, web/css (LESS en el tema clásico, con source/, theme.less y variables), web/js, web/fonts, web/images, i18n/ y media/preview.jpg. Se activa en Content → Design → Configuration por store view, y se compila con setup:static-content:deploy (o en developer mode con dev:source-theme:deploy para LESS). La herencia permite sobrescribir solo lo necesario; cuanto más overrides, mayor costo de upgrade. En Hyvä el tema se estructura de forma distinta (componentes Tailwind/Alpine, sin LESS ni RequireJS).

Q50. ¿Qué opciones hay para un storefront moderno: PWA Studio, Hyvä y headless?

La elección depende del equipo disponible, del número de extensiones críticas (algunas solo funcionan en el frontend clásico) y de los objetivos de rendimiento/SEO.

Q51. ¿Cómo se manejan internacionalización, traducciones y locales?

Las frases se envuelven con __('Texto') en PHP y con data-bind="i18n: '...'"/i18n en JS/HTML. Cada módulo y tema tiene i18n/es_ES.csv (y i18n/es_MX.csv, etc.) con pares «original,traducción»; se recolectan con bin/magento i18n:collect-phrases y se pueden generar diccionarios por tema con i18n:pack. Los locales se asignan por store view (general/locale/code) e influyen en formatos de fecha, moneda y números; las traducciones del admin se resuelven por el idioma del usuario. Consideraciones: textos con variables posicionales (%1), plurales, traducciones por store view de atributos EAV (nombre, descripción) y de contenido CMS (bloques y páginas por store view o con Content Staging), y la generación de estáticos por locale en el despliegue (setup:static-content:deploy es_ES).

Q52. ¿Cómo se depura el frontend?

Herramientas y técnicas: Template Path Hints (Developer → Debug, por store view) para saber qué archivo se está renderizando y de qué módulo/tema; Layout handles y bloques con el hint de layout o imprimiendo $this->getRequest()->getFullActionName(); Profiler integrado (Mage::profiler / habilitar en index.php o en Cloud con Blackfire) para ver tiempos por bloque; cache de layout y block_html deshabilitados mientras se desarrolla (cache:disable layout block_html full_page); developer mode para ver excepciones y regeneración de assets; devtools del navegador para RequireJS (errores de paths, módulos no cargados) y para Knockout en checkout; y var/log (system.log, debug.log, exception.log) con el logger configurado. En problemas de CSS/LESS suele bastar con borrar var/view_preprocessed y pub/static del tema y volver a desplegar.

7. Funcionalidad de comercio

Q53. ¿Cómo funciona el flujo de compra de punta a punta?

Quote (quote, quote_item, quote_address): el carrito acumula ítems, direcciones (billing/shipping, con modo multishipping), método de envío, método de pago, reglas de descuento e impuestos; los total collectors (subtotal, discount, shipping, tax, grand_total) se ejecutan en orden definido y pueden extenderse con collectores custom. Al confirmar, el quote se convierte en Order (sales_order) mediante el servicio CartManagementInterface::placeOrder, se reserva inventario (reservations en MSI) y se emiten eventos. Después: Invoice (captura del pago, parcial o total), Shipment (con tracking, packing slips y, en MSI, selección de source), y Credit Memo (devoluciones/reembolsos, con RMA en Commerce). Cada documento tiene su numeración incremental y sus estados/estados de orden configurables por state (new, processing, complete, closed, canceled, holded, payment_review) con transiciones y notificaciones por correo.

Q54. ¿Cómo se configuran los métodos de pago y qué consideraciones PCI aplican?

Magento trae métodos offline (cheque, transferencia, contra reembolso, purchase order en B2B) y conectores con pasarelas; en las versiones recientes Adobe impulsa Payment Services y los conectores de terceros (Stripe, Adyen, PayPal/Braintree, Mercado Pago y locales de LATAM) se distribuyen como extensiones del Marketplace o paquetes Composer. Cada método implementa una interfaz del modelo de pago (MethodInterface: isAvailable, authorize, capture, refund, void, canUseForCurrency/Country) con su propio config provider para el checkout. Consideraciones PCI: no almacenar PAN en la base de datos; usar tokenización y campos hospedados/redirect del proveedor para quedar en SAQ-A/A-EP; cifrar credenciales del método (Magento cifra los valores de configuración sensibles con la crypt key de env.php); registrar sin exponer datos de tarjeta; y validar 3-D Secure donde aplique. En auditorías se revisa también el alcance del CDE: separar el entorno de pago y limitar el acceso al admin.

Q55. ¿Cómo funcionan los métodos de envío y las table rates?

Métodos nativos: Flat Rate (tarifa fija por pedido o por ítem), Free Shipping (con umbral de subtotal), Table Rates (matriz CSV por website con combinaciones de país/región/código postal contra peso, subtotal o número de ítems) y In-Store Pickup (con MSI). Los transportistas (UPS, FedEx, USPS, DHL) existían en el core y en versiones recientes se distribuyen como módulos separados; en proyectos LATAM se suelen integrar operadores locales o agregadores (por ejemplo, servicios de última milla) mediante extensiones o desarrollo propio implementando CarrierInterface con collectRates. El cálculo de tarifas ocurre durante el quote (por dirección de destino, peso volumétrico, dimensiones del producto y reglas de caja), y las restricciones de país/región y los handling fees se configuran por scope. Puntos críticos: mantener limpias las tablas de tarifas, validar pesos/dimensiones del catálogo y probar múltiples direcciones y multishipping.

Q56. ¿Qué es MSI (Multi-Source Inventory) y cómo gestiona el stock?

MSI, introducido en 2.3 y estándar en 2.4, desacopla el inventario de la noción de «un solo almacén»: define Sources (ubicaciones físicas con cantidad y estado habilitado), Stocks (agrupaciones lógicas de sources asociadas a un website, con reglas de priorización y de selección de source) y Salable Quantity (cantidad vendible calculada por source/stock). Los movimientos generan reservations (no bloqueos físicos) que descuentan la cantidad vendible al reservar y se liberan/consumen con el envío o la cancelación, con comandos de consistencia (inventory:reservation:*) para corregir desfases. Además soporta in-store pickup, entregas parciales desde varios sources y transferencias internas. Para integraciones con ERP/WMS es crucial decidir la fuente de verdad del stock y cómo se sincronizan (API de StockItem/SourceItem o bulk API) y gestionar la concurrencia para no vender stock inexistente.

Q57. ¿Cómo funcionan las reglas de precio de carrito y de catálogo?

Buenas prácticas: documentar la matriz de promociones, probar combinaciones (impuestos, envío, MSI, multi-store) y vigilar el impacto en el índice de sales_rule y en el rendimiento del carrito cuando hay muchas reglas activas.

Q58. ¿Cómo se configuran los impuestos?

El motor nativo combina: product tax classes (qué tipo de producto), customer tax classes (qué tipo de cliente), tax zones/rates (por país, región y código postal, con rangos y porcentajes) y tax rules que cruzan las tres dimensiones; además se define si los precios se ingresan incluyendo o excluyendo impuestos (price_includes_tax), el cálculo de envío y descuentos (antes/después de impuesto), y el redondeo por ítem o por dirección. El Fixed Product Tax (FPT) y Weee cubren tasas por unidad (RAEE). Para IVA europeo existen VAT ID validation, grupos de clientes automáticos por validez del número y reglas intra-comunitarias. En países de LATAM con regímenes complejos (retenciones, percepciones, facturas electrónicas) se suele requerir una extensión de localización que integre impuestos adicionales, numeración y documentos fiscales con el ERP.

Q59. ¿Cómo se gestiona el contenido: CMS, Page Builder y Content Staging?

El CMS nativo incluye páginas (cms_page) con layout XML personalizado por página, bloques estáticos reutilizables, widgets (bloques con parámetros insertables en contenido: productos, categorías, banners) y jerarquía de URL. Page Builder (Adobe Commerce) ofrece edición visual drag-and-drop con tipos de contenido (filas, columnas, tabs, sliders, video, mapas, productos) guardados como contenido estructurado; en Open Source hay editores WYSIWYG estándar y módulos de terceros. Content Staging & Preview (Commerce) permite programar campañas: cambios de páginas, bloques, reglas de precio, categorías y productos con fecha de inicio/fin y previsualización. Buenas prácticas: versionar el contenido crítico, cuidar el impacto en caché (contenido dinámico rompe el FPC) y validar el rendimiento de páginas con mucho Page Builder.

Q60. ¿Cómo se trabaja el SEO técnico en Magento?

Elementos nativos: URL keys por producto/categoría/CMS con URL rewrites (url_rewrite) que preservan rutas antiguas con 301, canonical tags configurables por tipo de página, meta título/descripción/keywords por producto, categoría y página, sitemap XML generable programado por store view (con imágenes), atributos alt de imágenes, breadcrumbs, paginación con rel prev/next según versión, control de páginas indexables (robots.txt, meta robots por handle), y rich snippets (schema.org JSON-LD para producto, precio, disponibilidad y reviews, a menudo reforzado con extensiones). Buenas prácticas: evitar contenido duplicado entre store views y parámetros de filtro (canonical hacia la categoría base, noindex en facetas paginadas), cuidar los Core Web Vitals (LCP/CLS/INP) con temas livianos e imágenes optimizadas, y gestionar correctamente las redirecciones en cada cambio de catálogo.

Q61. ¿Cómo son las operaciones de back-office: órdenes, devoluciones, facturación e informes?

El admin (Sales) permite crear órdenes manualmente (con precios personalizados y notas), ponerlas en hold, cancelar, facturar (parcial o total, con captura online/offline), generar envíos con tracking y packing slips, y crear notas de crédito; los correos transaccionales son plantillas configurables por store view. RMA (Commerce) gestiona solicitudes de devolución con motivos, autorización, recepción y reembolso/cambio. Informes: ventas, impuestos, envíos, productos más vendidos/vistos/añadidos, clientes, carritos abandonados, búsquedas y términos, cupones y stock bajo; se alimentan de tablas de estadísticas que deben actualizarse por cron. También hay operaciones masivas (exportación de órdenes, actualización de atributos por lote, import/export de productos y precios por CSV) y flujos de aprobación B2B. En implementaciones grandes estos procesos se automatizan con integraciones al ERP y se reservan en Magento las tareas de atención al cliente.

8. Rendimiento, indexación y caché

Q62. ¿Cómo funcionan los indexadores y qué modos tienen?

Los indexadores materializan datos calculados (precios, categoría-producto, EAV para filtros, búsqueda, reglas de venta, inventario) en tablas o en el motor de búsqueda, porque calcularlos en cada petición sería inviable. Se declaran en etc/indexer.xml con su IndexerInterface (executeFull, executeList, executeRow) y vistas de datos. Cada indexador tiene un modo: Update on Save (se recalcula inmediatamente tras cada cambio, adecuado en catálogos pequeños o en desarrollo) o Schedule (los cambios se registran en tablas *_cl de changelog y un cron los procesa por lotes, usando MVIEW; es lo recomendado en producción). Comandos: indexer:info, indexer:show-mode, indexer:set-mode, indexer:status, indexer:reindex [id], indexer:reset. Buenas prácticas: reindexar fuera de horas pico, vigilar cron_schedule del grupo index, revisar el tamaño de las tablas de changelog y de las de índice, y evitar reindexados completos innecesarios (rompen la caché y saturan la BD).

Q63. ¿Qué tipos de caché hay y cómo se gestionan?

Magento define tipos de caché (visibles en System → Cache Management y en app/etc/env.php): config, layout, block_html, collections, reflection, db_ddl, compiled_config, eav, config_integration, config_integration_api, full_page, config_webservice y translate. Cada entrada tiene tags que permiten invalidación selectiva cuando cambia un producto, categoría, bloque CMS o configuración. El backend por defecto es el filesystem (var/cache), pero en producción se usa Redis (o Varnish para full_page). Comandos: cache:status, cache:enable/disable, cache:clean (invalida por tipos) y cache:flush (vacía todo el storage). Errores frecuentes: tener caché deshabilitada en producción, mezclar entornos con el mismo Redis (usar prefijos distintos), y no invalidar tras cambios de configuración importada.

Q64. ¿Cómo se configura Varnish y cómo se manejan los agujeros del full page cache?

Se activa full_page con Varnish (Admin → Full Page Cache → Varnish Caching, que genera el VCL con backend, TTL, reglas de bypass para admin/checkout/usuario logueado y purga por tags). El FPC almacena el HTML completo y devuelve la página sin ejecutar PHP, con mejoras enormes en TTFB. Los contenidos que no pueden cachearse (carrito, minicart, mensajes, wishlist, precios por cliente logueado) se resuelven con agujeros: bloques marcados con cacheable="false" o con getCacheKeyInfo/getEsi y renderizado por AJAX/ESI en el navegador. En arquitecturas con CDN (Fastly en Cloud) se usan reglas equivalentes de edge y surrogate keys. Buenas prácticas: revisar los tags para que una actualización de producto no purgue toda la caché, medir el hit rate, no cachear respuestas con cookies de sesión y probar el comportamiento de checkout y de páginas con contenido personalizado.

Q65. ¿Cómo se usa Redis para cache, page cache y sesiones?

En app/etc/env.php se configuran los backends: cache → frontend con idPrefix propio por entorno/instalación, servidor, puerto, base de datos, compression_lib, y opciones de two-tier (caché local en memoria del worker + Redis compartido) para reducir latencia; un frontend específico para page_cache (si no se usa Varnish) y session save = redis con sus propios idPrefix, disable_locking, max_concurrency y break_after_*. Ajustes clave: maxmemory-policy (allkeys-lru para cache, noeviction para sesiones), timeouts y reintentos, monitoreo de evicted_keys y del hit rate, y no compartir la misma base Redis entre staging y producción. Una sesión mal configurada produce cuelgues por lock (varios requests concurrentes del mismo usuario) y problemas de login intermitentes.

Q66. ¿Qué papel juegan Elasticsearch/OpenSearch y cómo se optimizan?

Desde 2.4.4 el motor de búsqueda es obligatorio y externo: Elasticsearch u OpenSearch. Se usa para: búsqueda del catálogo (relevancia, sinónimos, corrección de errores, sugerencias), facetas/filtros de la navegación por capas y los listados de categoría. El indexador catalogsearch_fulltext construye el índice con los atributos marcados como searchables/filterable, mapeados por tipo. Optimización: dimensionar memoria (heap) y shards/réplicas según el catálogo, ajustar refresh_interval, revisar la relevancia (pesos por atributo, sinónimos y stopwords por idioma), monitorear consultas lentas y el tamaño del índice, y evitar reindexados completos innecesarios. En Adobe Commerce existe además Live Search (servicio de Adobe con SaaS de búsqueda, mejor relevancia y facets en el edge). Síntomas de un mal setup: resultados incorrectos, timeouts en listados y picos de CPU en el nodo.

Q67. ¿Cómo se optimiza el rendimiento del frontend (assets, imágenes, CDN)?

Acciones de mayor impacto: (1) producción con setup:di:compile y setup:static-content:deploy, minificación y bundling de JS/CSS (Advanced JavaScript/CSS Processing), y firma de estáticos para cache agresiva; (2) CDN para pub/static y pub/media (base URL de estáticos en otro dominio, Fastly/CloudFront/Cloudflare) con TTL largos y purga por versión; (3) imágenes: dimensiones definidas en view.xml, formatos modernos (WebP/AVIF) y lazy loading, sin servir la imagen original en listados; (4) reducir JavaScript del storefront (Hyvä o headless ayudan notablemente), deferir scripts y evitar extensiones que inyecten código en cada página; (5) FPC + Varnish con buen hit rate; (6) opcache de PHP-FPM activado y afinado, y (7) medir con Core Web Vitals (LCP, CLS, INP) y RUM real, no solo con pruebas de laboratorio.

Q68. ¿Cómo se diagnostica un problema de lentitud?

Método: (1) caracterizar (páginas afectadas, usuarios, horarios, si el problema es TTFB o render o backend/checkout/admin); (2) medir: profiler integrado o Blackfire/New Relic (en Cloud vienen incluidos) para ver tiempo por función; slow query log de MySQL y EXPLAIN de las consultas repetidas; logs de PHP-FPM (slowlog, request_slowlog_timeout); (3) causas habituales: N+1 por cargar colecciones dentro de bucles, plugins sobre métodos calientes (precio, stock, getList), indexadores en modo Update on Save con catálogo grande, caché deshabilitada o mal invalidada, sesiones en disco, Elasticsearch saturado, cron acumulado, y extensiones que inyectan JS/bloques en todas las páginas; (4) corregir: consultas por lotes, caché por bloque, indexers en schedule, opcache, y retirar módulos inútiles (module:disable). Después se vuelve a medir para validar la mejora con números.

Q69. ¿Cómo se dimensiona la infraestructura y qué buenas prácticas de base de datos aplican?

Dimensionamiento según tráfico y catálogo: separar web (PHP-FPM + nginx, escalado horizontal detrás de load balancer con sesiones en Redis), base de datos (instancia dedicada, discos NVMe/SSD, réplica de lectura para reporting), Elasticsearch/OpenSearch (nodos propios con heap adecuado), Redis (cache y sesiones, idealmente instancias separadas) y Varnish/CDN en el edge. En MySQL: innodb_buffer_pool_size (60–80% de RAM en servidor dedicado), max_connections coherente con workers PHP-FPM (pm.max_children), innodb_log_file_size, y análisis periódico de índices. Buenas prácticas: limpieza de tablas crecientes (report_*, customer_log, catalog_product_entity_varchar huérfanos, sesiones y logs), archiving de órdenes antiguas si el volumen lo exige, backups con pruebas de restauración y separación de entornos para no competir por recursos.

9. Integraciones y APIs

Q70. ¿Qué APIs expone Magento y cuándo usar cada una?

Q71. ¿Cómo se autentica una integración?

Mecanismos: (1) Admin token: POST /rest/V1/integration/admin/token con usuario y contraseña del admin, devuelve un token usado como Bearer; el token expira (configurable en Stores → Configuration → Services → OAuth → Access Token Expiration). (2) Customer token: POST /rest/V1/integration/customer/token para APIs de cliente. (3) Integration tokens: se crea una Integration en el admin, se eligen los permisos por recurso API y se generan tokens de acceso (flujo OAuth 1.0a), lo que permite mínimo privilegio y auditoría. (4) JWT: desde 2.4.7 hay soporte de tokens JWT para admin y cliente (verificar en la versión concreta), que facilita validación sin estado. Buenas prácticas: usuarios e integraciones dedicadas por sistema, permisos mínimos por recurso, rotación periódica, almacenamiento en gestor de secretos, HTTPS obligatorio, rate limiting y registro de llamadas.

Q72. ¿Cómo funciona GraphQL y cómo se crean esquemas y resolvers custom?

El esquema se declara en schema.graphqls dentro de cada módulo: se añaden tipos, campos extendidos de tipos existentes (extend type ProductInterface), queries/mutations y argumentos, y se asocia cada campo a un resolver (ResolverInterface::resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null)) que devuelve datos o un callable diferido. Los módulos se fusionan, por lo que varios módulos pueden extender el mismo tipo. Existen resolvers por lotes (BatchResolverInterface) para evitar N+1 al resolver campos de listas, y soporte de caché de identidad (IdentityInterface) para invalidar con el FPC/edge. Buenas prácticas: delegar en service contracts en el resolver (no acceder directo a modelos), paginar siempre, controlar la complejidad/profundidad de las queries (query depth/complexity limits) y exponer solo lo que el storefront necesita.

Q73. ¿Cómo se consume la API REST para catálogo, stock y órdenes desde un ERP/PIM?

Endpoints habituales: productos (GET/POST/PUT /V1/products, con searchCriteria para consultas y custom_attributes para EAV), atributos y attribute sets (/V1/products/attributes), categorías y asignaciones (/V1/categories, /V1/categories/:id/products), imágenes (/V1/products/:sku/media con upload base64), precios y tier prices, stock (/V1/stockItems/:sku y en MSI /V1/inventory/source-items y /V1/inventory/bulk-product-source-assign), clientes (/V1/customers) y ventas (/V1/orders, /V1/invoices, /V1/shipments, /V1/creditmemos, más /V1/orders/create para órdenes desde el ERP). Patrones recomendados: paginación con searchCriteria y pageSize, actualizaciones parciales (PUT con solo los campos que cambian), sincronización incremental por updated_at, y bulk API para volúmenes altos. Definir la fuente de verdad por campo (por ejemplo, precio y stock en el ERP, descripciones en el PIM) es la decisión más importante del diseño.

Q74. ¿Qué es la API asíncrona/bulk y cómo funcionan las message queues?

La async/bulk API permite enviar operaciones masivas (por ejemplo, crear o actualizar cientos de productos) que se encolan en lugar de ejecutarse en la petición: se responde con un bulkId/lista de operationIds y el estado se consulta en /V1/bulk/:bulkId. Por debajo está el framework de message queue: tópicos declarados en etc/communication.xml, publishers (etc/queue_publisher.xml) y consumers (etc/queue_consumer.xml) que procesan mensajes desde RabbitMQ o MySQL como broker. El core lo usa para indexación, envío de correos, exportaciones, sincronización de inventario y operaciones de Adobe Commerce Cloud. En producción se ejecutan los consumers como procesos dedicados (systemd/supervisor o bin/magento queue:consumers:start), con configuración de maxMessages, reintentos y dead-letter. Ventajas: no bloquear la petición HTTP, reintentos automáticos y picos de carga absorbidos por la cola.

Q75. ¿Cómo se implementan webhooks y notificaciones de eventos hacia sistemas externos?

Opciones: (1) el módulo de Webhooks de Adobe Commerce (configurable en el admin) que publica eventos de negocio (orden creada, cliente actualizado, producto guardado) hacia URLs externas con firma y reintentos; (2) desarrollo propio: un observador o plugin que publica un mensaje en una cola y un consumer que hace el POST al sistema destino con retry/backoff y registro del resultado; (3) endpoints de recepción: controladores custom (clase que implementa HttpRequestHandlerInterface y se expone en etc/webapi.xml o en etc/frontend/di.xml con routers) para recibir callbacks de pasarelas de pago o transportistas. Diseño seguro y robusto: validar firma/token del callback, responder rápido (202) y procesar en cola, verificar idempotencia con el id del evento, no exponer datos sensibles en la URL y registrar cada intento para auditoría y reproceso.

Q76. ¿Cómo se diseña una integración robusta con Magento?

Principios: idempotencia (usar SKU/order increment id/external id como clave natural y upsert en lugar de create; Magento rechaza SKUs duplicados, lo que ayuda), lotes (bulk API o paginación con searchCriteria, nunca un request por registro), asincronía (colas para no chocar con timeouts HTTP ni con limit_time_real), reintentos con backoff y límite máximo + dead letter, logging por mensaje (payload resumido, estado, error, intentos) y alertas, gestión de concurrencia (evitar dos procesos actualizando el mismo producto/stock), manejo de errores específicos (NoSuchEntityException, InputException, CouldNotSaveException, 401/403, 429/503) y contratos versionados. Además: probar con datos reales en staging, definir ventanas de sincronización y un mecanismo de reconciliación periódica (full sync nocturno) para corregir desviaciones.

Q77. ¿Cómo se integra Magento con ERP, PIM, OMS y sistemas locales de pago/logística?

Patrones habituales: ERP (SAP, Oracle, Dynamics, NetSuite, Odoo) como fuente de precios contractuales, stock, clientes/crédito y facturas, sincronizando por API o por archivos intermedios con un middleware/iPaaS (MuleSoft, Boomi, Celigo, n8n, Kafka Connect); PIM (Akeneo, Pimcore, inRiver) como fuente de datos de producto y medios, publicando hacia Magento con bulk API; OMS/WMS para orquestar fulfillment multi-almacén y actualizar envíos y tracking; pasarelas y agregadores locales (en LATAM: Mercado Pago, dLocal, EBANX, PayU, Culqi, Wompi, entre otros) mediante extensiones del Marketplace o desarrollo propio del método de pago; y transportistas/last-mile con generación de guías y webhooks de tracking. La arquitectura recomendada es un middleware con colas y trazabilidad por mensaje, y no integraciones punto a punto entre todos los sistemas, porque multiplican el mantenimiento y dificultan la reconciliación.

10. Seguridad, multi-store, calidad y administración

Q78. ¿Qué prácticas de seguridad son críticas en Magento?

Q79. ¿Cómo se gestionan los parches de seguridad y de calidad?

Con el paquete magento/quality-patches (plugin de Composer) se listan y aplican parches sin subir de versión: en composer.json se declaran bajo extra → magento-quality-patches → patches y se aplican automáticamente durante composer install/update y al ejecutar setup:upgrade (en Adobe Commerce Cloud se gestionan con vendor/bin/ece-patches). Comandos útiles: vendor/bin/magento-quality-patches status (ver aplicados/disponibles) y list-patches. Cada parche se documenta (ID, motivo, ticket de Adobe, versión en la que se incluye) y se retira al actualizar. En Cloud los parches de seguridad críticos pueden aplicarse por la plataforma. Alternativa histórica: parches sueltos con cweagans/composer-patches. Lo importante es tener un proceso: monitoreo del boletín de seguridad de Adobe, ventana de aplicación, prueba en staging y despliegue rápido.

Q80. ¿Qué es la CSP (Content Security Policy) y cómo afecta a los desarrollos?

Magento incorpora un módulo de Content Security Policy que en versiones recientes opera en modo report-only por defecto y puede pasar a modo restrict: limita qué dominios pueden servir/ser cargados por scripts, iframes, imágenes, estilos y conexiones, mitigando XSS y skimming. Impacto en desarrollo: los inline scripts y estilos quedan bloqueados, por lo que hay que moverlos a archivos o usar nonces/hash según la implementación; y cada dominio de terceros (pasarelas de pago, analytics, chat, CDNs, mapas) debe declararse en csp_whitelist.xml del módulo correspondiente. Buenas prácticas: empezar en report-only, revisar los reportes para identificar violaciones, ajustar la whitelist al mínimo necesario, verificar checkout y widgets de terceros antes de pasar a restrict, y documentar los dominios permitidos por qué lo están.

Q81. ¿Cómo se configura multi-website, multi-store, multi-idioma y multi-moneda?

La jerarquía es Website → Store → Store View: los websites separan catálogos, clientes, precios base, métodos de pago/envío y dominios; las stores agrupan categorías/estructuras de navegación dentro de un website; las store views varian idioma, moneda de visualización y contenido traducido. Se configura en Stores → All Stores, asignando dominios/carpetas y códigos, y creando variables de servidor (MAGE_RUN_CODE, MAGE_RUN_TYPE) o reglas en nginx para enrutar por dominio. Los precios pueden fijarse por website (scope del atributo price), las monedas se habilitan con tasas (manuales o por servicio) y las traducciones por store view. Consideraciones: URL rewrites y canonical por store view, sitemap separados, reglas de impuestos/envío por website, y pruebas específicas de cada tienda porque los bugs de scope son frecuentes.

Q82. ¿Cómo se gestiona la calidad: tests y estándares de código?

En CI se ejecutan al menos estáticos + unitarios en cada PR, y los de integración/MFTF en merges o nightly por su costo. A esto se suman revisiones de código con criterios Magento (nada de Object Manager directo, sin overrides innecesarios, contratos públicos para lo que se expone).

Q83. ¿Cómo se afronta un upgrade de versión y qué se debe validar?

Plan: (1) inventario (versión actual, extensiones y su compatibilidad con la versión destino, módulos propios, temas, integraciones, volumen de datos); (2) preparar entorno de prueba con copia de producción y ejecutar el upgrade con Composer (composer require magento/product-*:2.4.x + composer update), luego setup:upgrade, setup:di:compile, setup:static-content:deploy; (3) corregir código propio por deprecaciones, cambios de interfaces, cambios en el esquema y en requisitos de PHP/OpenSearch; (4) regresión funcional: checkout completo (todos los métodos de pago y envío), búsqueda y facetas, precios y promociones, admin (grids y formularios), APIs e integraciones (ERP/PIM/pasarelas), correos y cron; (5) rendimiento comparado antes/después; (6) plan de corte con snapshot y rollback definido. Los upgrades se presupuestan como proyecto y no deben dejarse para último momento: una versión sin soporte es riesgo de seguridad.

Q84. ¿Qué se monitorea y cómo se administra una tienda en producción?

Monitoreo: disponibilidad y latencia (uptime sintético del home, PLP, PDP y checkout), APM (New Relic/Blackfire/Datadog: tiempo por transacción, errores PHP, consultas lentas), infraestructura (CPU, RAM, disco, red de web/BD/Redis/OpenSearch), aplicación (jobs cron atrasados o fallidos en cron_schedule, consumers de cola con backlog, hit rate de Varnish/Redis, errores 5xx en nginx, tamaño de logs), negocio (órdenes por hora, tasa de conversión, carritos abandonados, fallos de pago) y seguridad (intentos de login al admin, cambios de archivos, tráfico de bots). Operación: backups/snapshots automáticos con prueba de restauración, gestión de cambios con ventanas y aprobación, runbooks para incidentes comunes (caída de OpenSearch, Redis lleno, cron bloqueado), y revisiones periódicas de usuarios, permisos, integraciones y extensiones instaladas.

Q85. ¿Qué buenas prácticas de proyecto y gobierno recomiendas en una implementación Magento?

11. Cómo responder preguntas de Magento en una entrevista (plantilla)

Pregunta típica: «¿Cuál es su experiencia con Magento / Adobe Commerce en desarrollo, configuración, integraciones y administración?»

Respuesta modelo (adapta los corchetes con tu experiencia real)

Apertura (sí + estructura): «Sí. He trabajado con Magento [Open Source / Adobe Commerce] versión [2.4.x] durante [X] años en tiendas de [sector/país], cubriendo configuración funcional, desarrollo de módulos y temas, integraciones con [ERP/PIM/pasarelas] y administración de la plataforma en [on-premise / Adobe Commerce Cloud]».

Desarrollo: «Desarrollo módulos con la estructura estándar (registration.php, module.xml, di.xml, db_schema.xml, webapi.xml): modelos y repositorios con service contracts, plugins (before/after/around) en lugar de preferencias siempre que es posible, observers para eventos del core, cron jobs y patches de datos. Uso inyección por constructor, factories y virtual types, y evito el Object Manager directo».

Frontend y experiencia: «He trabajado con layout XML (handles, containers, referenceBlock), bloques con ViewModels, templates PHTML y UI Components en el admin; en JavaScript con RequireJS y mixins [y con Hyvä / PWA Studio consumiendo GraphQL en proyectos headless]».

Configuración funcional: «He configurado catálogo con productos [simples/configurables/bundle], reglas de precio de carrito y de catálogo, impuestos por [país], métodos de envío y pago, MSI con múltiples sources, y multi-store con [N] websites y store views en varios idiomas y monedas».

Integraciones: «He integrado con [ERP/PIM/OMS] usando la API REST con tokens de integración, SearchCriteria para consultas, bulk/async API para volúmenes altos y colas (RabbitMQ) con reintentos e idempotencia; también GraphQL para storefront headless».

Rendimiento y operación: «Administro indexadores en modo schedule, Redis para cache/sesiones, Varnish/CDN para full page cache y OpenSearch; he optimizado [ejemplo: TTFB, LCP, tiempo de reindexado] y opero despliegues con di:compile y static-content:deploy, backups y monitoreo (New Relic/Blackfire/logs)».

Cierre (resultados + aplicación al rol): «En mis proyectos logré [métrica: conversión +X%, tiempo de carga -Y%, integración de N sistemas, upgrade de versión sin incidentes]. En este rol aportaría [desarrollo/arquitectura de integraciones/optimización] y ayudaría a priorizar estándar frente a customizaciones para reducir la deuda de upgrades».

Evidencia sugerida por área (elige lo que realmente hayas hecho)

ÁreaQué mencionarImpacto demostrable
Desarrollo de módulosEstructura de módulo, DI, plugins, service contracts, db_schema, patches de datosMódulos en producción, repositorio propio, extensiones publicadas
Frontend/temasLayout XML, bloques y ViewModels, temas hijos, RequireJS/mixins, Hyvä o PWAMejoras de Core Web Vitals, storefront personalizado
Catálogo y merchandisingTipos de producto, atributos EAV, categorías, reglas de precio, MSICatálogos de N SKUs operando, campañas de promoción
Checkout y pagosMétodos de pago/envío, total collectors, tokenización, alcance PCIConversión mejorada, menos fallos de pago
IntegracionesREST/GraphQL/SOAP, bulk API, colas, webhooks, middlewareSincronizaciones estables con ERP/PIM, volumen de transacciones
RendimientoIndexers en schedule, Redis, Varnish/Fastly, OpenSearch, profilingReducciones medibles de TTFB/LCP y de tiempo de reindexado
SeguridadParches de calidad, 2FA, CSP, hardening, auditoría de extensionesHallazgos remediados, cumplimiento PCI, cero incidentes
DevOps y administraciónModos de despliegue, pipelines, Cloud/ece-tools, backups, monitoreoReleases predecibles, upgrades sin incidentes críticos

Consejos

12. Referencias

ReferenciaQué cubre
Adobe Commerce Developer Documentation (developer.adobe.com/commerce)Guías oficiales: arquitectura, DI, plugins, EAV, layout, UI Components, Web API, GraphQL, MSI, testing y despliegue.
Magento DevDocs - Best practices y coding standardsConvenciones de código, patrones recomendados y anti-patrones (Object Manager, overrides excesivos).
Código fuente en GitHub (magento/magento2)Referencia definitiva de interfaces, métodos y flujos internos; esencial para herencias y plugins.
Magento Coding Standard (paquete Composer)Reglas de PHP_CodeSniffer específicas de Magento para análisis estático en CI.
MFTF (Magento Functional Testing Framework)Pruebas funcionales end-to-end de UI con acciones en XML y datos generados.
Adobe Commerce Cloud docs (ece-tools)Configuración de entornos, .magento.app.yaml, despliegue, Fastly, snapshots y monitoreo.
Adobe Commerce MarketplaceExtensiones y temas certificados, con información de compatibilidad por versión.
Boletines y página de seguridad de Adobe CommerceParches de seguridad, versiones soportadas y fechas de fin de soporte.
magento/quality-patchesCatálogo y aplicación de parches de seguridad y calidad por versión.
Hyvä Themes / PWA StudioDocumentación de storefronts modernos: rendimiento, componentes y consumo de GraphQL.
OpenSearch / Elasticsearch y Redis / Varnish docsTuning de búsqueda, caché distribuida y caché HTTP de página completa.
Certificaciones Adobe (Commerce Developer / Architect)Rutas de certificación oficial con los temarios de arquitectura y desarrollo.