You rewrote your Magento auth endpoint in Go. It drops from 180ms to 8ms. You're thrilled.
Then you realize Go is still reading from customer_entity — with 5–10 JOINs across EAV tables. The bottleneck was never PHP. It was the schema.
So now what?
There are three paths forward when migrating Magento to a Go backend. Picking the wrong one early is expensive to undo.
Option A — Shared Database
Go connects directly to Magento's existing MySQL.
PHP Magento ──WRITE──▶ MySQL Magento (shared) ◀──READ── Go Service
◀──WRITE─ Go Service
What you get:
- ✅ Instant latency win (22× faster — PHP bootstrap overhead gone)
- ✅ Zero data sync lag — both systems read the same committed rows
- ✅ Trivial rollback — one config change flips traffic back to PHP
What breaks you later:
- ❌ Schema coupling — every Magento 2.4.x upgrade is a runtime risk for your Go structs
- ❌ EAV performance unchanged — Go executes the same 10-JOIN query, just faster
- ❌ Race conditions — writing to
oauth_tokenandcustomer_entityfrom both PHP and Go creates corrupted auth state, not a DB error - ❌ Distributed monolith trap — one failure domain, two codebases, harder to debug
Adobe deprecated the "split database" feature in Magento 2.4.6+. Every upgrade consolidates the schema further. Each Go struct pointing at a Magento table is an undeclared dependency with no SLA.
Use when: you need results in weeks. But set a hard Phase 2 deadline — this state becomes permanent by inertia.
Option B — CDC + Debezium ✅ Recommended
Debezium reads MySQL's binlog directly. Zero PHP code changes required.
PHP Magento ──WRITE──▶ MySQL Magento
│ binlog (no PHP changes needed)
▼
Debezium CDC Engine
│ stream events
▼
Go Service ──WRITE──▶ Go DB (flat schema, Go-owned)
# debezium-connector.yaml
connector.class: io.debezium.connector.mysql.MySqlConnector
database.hostname: magento-mysql-master
table.include.list: magento.customer_entity, magento.catalog_product_entity
# reads binlog — zero PHP changes required
Go writes use the Outbox Pattern — atomically within the same DB transaction:
// Single transaction — no dual-write risk
tx.Exec(`INSERT INTO go_customer_token (...) VALUES (...)`)
tx.Exec(`INSERT INTO go_outbox (event_type, payload) VALUES ('TOKEN_CREATED', $1)`, payload)
// OutboxProcessor publishes to Kafka every 500ms
What you get:
- ✅ Go owns its schema — flatten EAV → 5× read speed
- ✅ ACID writes on Go's own DB
- ✅ No PHP Magento code changes
- ✅ Per-domain rollout (Auth first, Checkout always last)
- ✅ CDC lag 50–200ms — acceptable for most use cases
Option C — Full Event Bus (Kafka)
Both systems fully isolated. All comms go through Kafka topics only.
EVENT BUS (Kafka)
┌──────────────────────────────────┐
│ customer.updated │ order.created │
└────────┬─────────────────┬───────┘
│ PUBLISH │ CONSUME
▼ ▼
PHP Magento Go Service
MySQL (owned) Go DB (owned)
The catch: Magento must publish every state change as a domain event. Customer updated, order status changed, inventory adjusted — all of it. If the PHP team misses a single event category, Go's DB silently diverges. Forever.
⚠️ Common mistake: Publishing directly to Kafka after the DB commit (not inside the transaction) creates a dual-write gap. If Kafka publish fails, the event is lost silently and Go's DB diverges permanently. Always use the Outbox Pattern — write to an outbox table inside the DB transaction first.
Use when: the PHP team can commit to building and maintaining the event publisher for every Magento domain. Timeline: 12–18 months.
The Decision Framework
Q1: 2+ engineers with distributed systems experience?
└─ NO → Option A + guardrails (schema pinning, read-only policy)
└─ YES → Q2
Q2: Inventory oversell tolerance = zero?
└─ YES → Option B (ACID writes, no eventual consistency at write time)
└─ NO → B or C both viable
Q3: Need Go to scale independently of Magento's DB?
└─ NO → Option B is sufficient
└─ YES → Q4
Q4: PHP team can build + maintain event publishers?
└─ NO → Option B required (CDC = no PHP changes)
└─ YES → Option C viable (12–18 months)
Domain Migration Order (regardless of option)
| Domain | Priority | Risk |
|---|---|---|
| Auth / OIDC | First | Low — Go already owns token logic |
| Wishlist | Second | Low — small data footprint |
| Customer read | Second | Medium — flatten EAV |
| Customer write | Third | Medium — needs Saga |
| Cart / Checkout | Last | High — never migrate until Saga is proven |
Full Breakdown
The full post includes a 16-dimension comparison matrix, risk table per option, infrastructure checklist (Debezium prerequisites), and a 24-month recommended roadmap.
👉 Read the full guide on tanhdev.com
Have you gone down the Event Bus route with Magento? Curious how the PHP event publisher held up in production — drop a comment below.
Top comments (0)