Engineering patterns from a large Adobe Commerce (Magento 2) B2B program—module and vendor names omitted.
Checkout is where money, carrier APIs, and ERP promises meet. On FORCE America–scale builds, the goal is not cleverness—it is predictable extension points, async boundaries, and upgrade paths that survive quarterly Magento security releases.
1. Plugins (interceptors) vs preferences vs observers
| Tool | Use when | Watch out |
|---|---|---|
| Plugin | Narrow behaviour change around a public method | Sort order chains; conflicting plugins |
| Preference | Replace a class entirely | Harder upgrades—last resort |
| Observer | React to domain events (sales_model_service_quote_submit_success) |
Ordering not guaranteed—document deps |
Rule of thumb
Prefer di.xml plugins on stable service contracts (QuoteManagement, PaymentInformationManagement) over rewriting controllers.
2. Extension attributes over “magic comments”
We stored structured checkout data—delivery appointment IDs, liftgate flags, customer cost center—as extension attributes on Quote / Order interfaces.
Why
- Survives GraphQL and REST serializers when exposed via schema extensions.
- Avoids parsing
customer_notein ERP jobs.
Implementation sketch
extension_attributes.xmldeclares fields.- Plugins populate defaults on quote create.
- Webapi XML maps fields for headless checkout if used.
3. Async integrations (PSP, tax, carrier)
Anti-pattern: call external HTTP inside submitQuote observer—adds latency and couples checkout to their SLA.
Pattern
- Persist intent on order (
payment_authrecord / queue job payload). - Queue
PlaceOrderfollow-up jobs with idempotency keys (order_id:step). - Retry with backoff; DLQ with alert after N failures.
4. GraphQL vs Luma checkout
If storefront is PWA Studio / custom React:
- Validate same business rules on GraphQL resolvers and any remaining Luma paths (admin reorders, phone orders).
- Share validation via service classes invoked from both—not copy-paste.
5. Upgrade and patch hygiene
- Magento quality patches applied on schedule; track diff vs. your plugins when core method signatures change.
- Composer
replacetricks—avoid unless you own the consequences. - Integration tests on
setup:di:compilein CI—catchesdi.xmlmistakes early.
6. Observability
- New Relic custom segments around
submitandplaceOrder. - Log correlation id (
quote_id/masked_id) across checkout + async jobs for support tickets.
Resume framing
“Led Adobe Commerce checkout work: DI plugins, extension attributes for structured payloads, async payment/carrier integrations with idempotent queues, and CI around compilation—aligned with security patch cadence.”