← Blog

Magento

Van Magento 1.9 naar 2.4.7: een Hyvä-rescue in 6 weken

Een bureau belt op een dinsdag. Hun klant draait €3,2M per jaar op Magento 1.9, de Sinterklaaspiek begint over acht weken, en de EOL-waarschuwingen stapelen zich op.

Jacob Molkenboer· Oprichter · A Brand New Company· 10 jun 2026· 9 min
Open leren grootboek met messing sleutel, crème indexkaart met groen lint en rode lakzegel op ivoorkleurig papier.

Een bureau belt op een dinsdag begin oktober. Hun klant runt een woonwinkel die €3,2M per jaar draait op Magento 1.9.4.3. De PHP 5.6 EOL-waarschuwing ligt al drie jaar op het bureau van de CTO. De Sinterklaaspiek begint in de tweede week van november. De deadline is niet onderhandelbaar, de URL-structuur is heilig, en de checkout mag tussen nu en 5 december op geen enkele zondag langer dan vier uur plat liggen.

Deze rebuild hebben we al meerdere keren gedaan. Dit is de playbook die we de klant op dag één overhandigen, en hij verandert per project nauwelijks.

De setup

Magento 1 bereikte op 30 juni 2020 het einde van zijn levenscyclus. Adobe stopte met patchen. PCI-compliance wordt elk kwartaal lastiger. De meeste shops die er in 2026 nog op draaien, zitten daar omdat de offerte voor een rebuild iemand de stuipen op het lijf joeg. Die offerte joeg iemand de stuipen op het lijf omdat oude offertes €120k waren voor een Luma-thema dat precies zo traag zou voelen als de oude shop.

Hyvä veranderde die rekensom. Het haalt de RequireJS- en KnockoutJS-frontend van Magento eruit en vervangt die door Tailwind plus Alpine.js. Een Lighthouse-score die vroeger drie weken frontend-operaties kostte, is nu de standaard. Een rebuild in zes weken is nu echt mogelijk, en daar is deze playbook omheen gebouwd.

De voorwaarden die we op dag één accepteren:

  • Geen wijzigingen in SKU- of categorie-URL's. Elke product-URL op de oude shop blijft werken op de nieuwe shop.
  • Eén checkout-freeze van vier uur, op één zondagochtend, vooraf afgesproken.
  • Klantwachtwoorden blijven geldig. Geen gedwongen reset-mails.
  • Bestelgeschiedenis zichtbaar voor klanten vanaf dag één van de nieuwe shop.

Week 1: audit en het freeze-venster

We schrijven in week één geen enkele regel themacode. We lezen.

De audit dekt vier dingen. Eerst de extensielijst. We exporteren de volledige lijst geïnstalleerde modules en geven ze een label: behouden, vervangen door native M2, vervangen door een Hyvä-compatibel alternatief, weg. Een typische M1-shop uit 2014 heeft zo'n 80 modules in app/code. De helft is dood. Ongeveer een kwart bestaat alleen omdat de merchant ooit om een gedrag heeft gevraagd dat het team uiteindelijk niet meer gebruikte.

Twee: de datavorm. We tellen rijen in de zware tabellen: catalog_product_entity, sales_order, customer_entity, url_rewrite. Voor deze shop: 11.400 producten, 84.000 orders, 31.200 klanten, 178.000 URL-rewrites. Zulke aantallen bepalen of de cutover vier uur of veertien uur duurt.

Drie: de integraties. We lijsten elk systeem dat Magento raakt: ERP, WMS, boekhouding, PSP, mailplatform, reviewplatform. Elk daarvan wordt een rij in een spreadsheet met twee kolommen: hoe het vandaag met M1 praat, hoe het op cutover-dag met M2 gaat praten.

Vier: het freeze-venster. We kijken naar de laatste twee jaar orderdata per uur. We zoeken het blok van vier uur met het laagste volume op een zondag binnen de afgesproken buffer. Voor deze shop was dat zondag 03:00 tot 07:00 CET. Die dag blokken we, schriftelijk, in de agenda van elke stakeholder.

Waarschuwing

Beloof nooit een zero-downtime cutover bij een rebuild van Magento 1 naar Magento 2. De ordertabel moet stilstaan terwijl je hem kopieert. Een korte, geplande, gecommuniceerde freeze is eerlijk. Een 'zero-downtime'-belofte wordt rond 04:00 een incident van zes uur.

Week 2: datamigratie en het URL-rewrite-contract

Adobe leverde een Data Migration Tool voor de sprong van M1 naar M2. Hij werkt. Het is ook een codebase uit 2017 die begeleiding nodig heeft. Wij gebruiken hem voor het zware werk (klanten, orders, EAV-attributen) en schrijven eigen scripts voor de rest.

Het URL-rewrite-contract is de technische belofte waar de merchant het meest om geeft. Google heeft elke SKU-pagina geïndexeerd. Affiliates hebben campagne-URL's hardcoded. Op e-mailtemplates uit 2019 wordt nog steeds geklikt. Een URL-wijziging is hier een Q4-omzetgebeurtenis, geen SEO-gebeurtenis.

Het eerste wat we op de nieuwe Magento 2.4.7-installatie doen: de oude core_url_rewrite-tabel exporteren en diffen tegen de nieuwe url_rewrite-tabel na de catalogus-import. Alles wat niet matcht, wordt een rij in een 301-map.

mysql -h m1-replica -e "SELECT request_path, target_path FROM core_url_rewrite \
  WHERE is_system = 0 OR product_id IS NOT NULL OR category_id IS NOT NULL" \
  store_old > /tmp/m1-rewrites.tsv

mysql -h m2 -e "SELECT request_path, target_path FROM url_rewrite \
  WHERE entity_type IN ('product','category')" \
  store_new > /tmp/m2-rewrites.tsv

comm -23 <(cut -f1 /tmp/m1-rewrites.tsv | sort -u) \
         <(cut -f1 /tmp/m2-rewrites.tsv | sort -u) \
  > /tmp/missing-rewrites.txt

Elke URL in missing-rewrites.txt heeft een antwoord nodig vóór de cutover. De meeste los je op door de URL-key op het nieuwe product aan te passen. De hardnekkige gaan als permanente 301-regels in nginx, zodat de merchant er nooit meer over hoeft na te denken.

Week 3: Hyvä-thema en de delen die we niet herbouwen

Week drie is de enige week die van buitenaf op een normaal Magento-project lijkt. We installeren het Hyvä Themes-pakket, genereren een child theme en beginnen met het overzetten van het ontwerp van de oude shop.

De regel waar we ons aan houden: geen redesign bij een rebuild. De merchant heeft niet om een redesign gevraagd. De merchant heeft om dezelfde shop op een werkende stack gevraagd. Als de homepage-layout binnen het bedrijf emotioneel gewicht heeft, kopiëren we hem pixel voor pixel, ook de stukken die we bij een greenfield-brief eruit zouden hebben gediscussieerd. Redesignwerk gaat in een aparte fase twee, na Sinterklaas.

Wat we wel stilletjes verbeteren, omdat Hyvä het bijna gratis maakt:

  • Largest Contentful Paint op de PDP, door de vier jQuery-plugins te verwijderen die op de oude shop image swap deden. Alpine doet hetzelfde gedrag in zo'n veertig regels.
  • Layered navigation, dat op M1 een XHR per klik deed en nu één Alpine state-object is.
  • De mini-cart, die vroeger een volledige Knockout-rerender triggerde en dat nu niet meer doet.

CMS-pagina's gaan mee via een klein script dat de M1 cms_page-tabel doorloopt en post naar de M2 REST API. Block-ID's worden hermapt, en elke inline asset-URL die naar het oude /media/wysiwyg/-pad wijst, wordt herschreven. De daadwerkelijke mediabestanden verplaatsen we met rsync, niet via de admin, omdat de admin-upload bestandsnamen herformatteert en deeplinks binnen CMS-content breekt.

Week 4: Hyvä Checkout en de payment-integraties

Hyvä Checkout is een apart product van het Hyvä-thema. Het vervangt de standaard checkout van Magento door een single-page-implementatie die de Knockout-laag helemaal weggooit. Hij is sneller, hij is schoner, en daar zit het meeste integratierisico bij een Nederlandse e-commerce-rebuild.

Nederlandse shops hebben iDEAL, Bancontact, Klarna nodig, soms Riverty, soms alles tegelijk. Meestal lopen ze via Mollie, MultiSafepay of Adyen. Elke PSP heeft een Hyvä Checkout-compatibiliteitsmodule. De meeste werken. Welke niet, ontdek je om 02:00 in de cutover-nacht. Dus test je ze in week vier.

De test die we altijd doen: een echte bestelling plaatsen, met een echte kaart, voor €0,01, via elke actieve betaalmethode, op een staging-omgeving die naar het productie-endpoint van de PSP wijst. Daarna terugboeken. Vervolgens een bestelling plaatsen, captureren, via de WMS-integratie verzenden, en checken of de order de juiste status toont in het ERP van de merchant. Als ergens een mens nodig is om 'even hier te klikken', krijgt die stap een automatiseringsticket vóór cutover.

Week 5: dry run op productiedata

Week vijf is de generale repetitie. We pakken op zondagavond een verse dump van de M1-productiedatabase, draaien de volledige migratiescripts erop tegen een kloon van de M2-productie-omgeving, en klokken elke stap. De eerste keer duurt de migratie elf uur. Bij de derde repetitie zitten we op drie uur en veertig minuten. De order-import is altijd de langste enkele stap. Klant-rehashing is altijd de tweede.

Deze week schrijven we ook het rollback-plan. Eén pagina, drie vertakkingen. Mislukt de migratie vóór de DNS-flip, doe niets en plan opnieuw. Lukt de migratie maar loopt de cutover-window over 07:00 heen, zet DNS terug op M1 en plan opnieuw. Verschijnt er binnen 24 uur na cutover een kritieke bug, dan herstel je vanaf de M1-snapshot van vóór de cutover. Elke vertakking heeft een eigenaar bij naam en een telefoonnummer op de pagina.

Week 6: cutover-weekend

Zaterdagmiddag: laatste M1-deployment-freeze. Na 16:00 gaat er niets meer naar M1. Marketing weet het. Klantenservice weet het.

Zaterdagavond: elk uur draait een delta-dump die alleen de rijen vastlegt die zijn veranderd sinds de laatste volledige dump. Die delta's komen in de queue voor replay.

Zondag 03:00: checkout uit op M1 met een vriendelijke onderhoudspagina. De catalogus blijft te bekijken. We nemen de laatste delta, replayen alle queued delta's op de staging M2, draaien integriteitschecks (ordercount, klantcount, totale omzet laatste 30 dagen, alles moet binnen de afgesproken tolerantie matchen), en draaien de URL-rewrite-diff voor het laatst.

Zondag 05:30: DNS-flip. De TTL was op vrijdag verlaagd naar 60 seconden. De nieuwe shop is live.

Zondag 06:00: smoke test. Een echt mens plaatst een echte bestelling met een echte kaart. De order komt aan in de WMS. De bevestigingsmail arriveert.

Zondag 07:00: aankondigen. Marketing stuurt de 'we zijn terug'-nieuwsbrief die op vrijdag is opgesteld.

Wat we verkeerd deden

Bij de eerste rescue die we zo aanpakten, hebben we de rehash van klantwachtwoorden onderschat. Magento 2 gebruikt standaard een ander hashing-schema, en de migration tool doet dat goed, maar we hadden het login-pad niet load-getest tegen 30.000 terugkerende klanten die in het eerste uur op de nieuwe shop binnenkwamen. Login was traag op zondagochtend. We hebben het opgelost door PHP-FPM warm te draaien en de Redis-connection-pool te vergroten, maar we hadden het in week vijf moeten zien.

Bij een latere rescue leverden we een checkout die perfect werkte met één PSP, maar stilletjes faalde bij één specifieke iDEAL-bank op mobile Safari. De Hyvä Checkout-module van die PSP had een bug in hoe hij de issuer-ID serialiseerde. We vingen het op omdat een klantenservice-medewerker binnen twee uur na cutover een klacht doorstuurde. Binnen het uur gepatcht. Sindsdien hebben we een testmatrix die bij elke rebuild precies die bank, op precies die browser, meeneemt.

Het patroon: de dingen die je bijten zitten nooit in de catalogusmigratie. Ze zitten in de long tail aan integraties die niemand heeft gedocumenteerd, omdat ze al negen jaar werkten.

Hoe het werk eruitziet

Toen we deze rescue vorig jaar voor een homeware-klant draaiden, was het ding waar we steeds tegenaan liepen de staart van URL-rewrites. Ze hadden een custom blogmodule die rewrites naar een niet-standaard tabel schreef. We hebben het opgelost door ons diff-script uit te breiden zodat het ook die tabel leest, en dat zit nu in onze standaard-kit. Dat soort op-maat legacy migration-werk is het meeste van wat we doen voor bureaus die een Magento-rebuild nodig hebben zonder de piek te verliezen.

Het kleinste wat je vandaag kunt doen: exporteer je core_url_rewrite-tabel naar een TSV-bestand, tel de rijen waar is_system = 0, en zet dat getal in een gedeeld doc. Dat getal is de omvang van het contract dat je op het punt staat met Google af te sluiten.

Kern

Een rescue van Magento 1 naar 2.4.7 met Hyvä is een klus van zes weken, mits je het URL-contract beschermt, de freeze schriftelijk inplant, en de cutover op echte data repeteert.

FAQ

Is zes weken echt genoeg om een Magento 1-shop van €3M te migreren?

Ja, mits je de voorwaarden van de playbook accepteert: geen redesign, één geplande checkout-freeze, een bevroren URL-contract, en een strakke integratiescope. Een redesign of scope creep verdubbelt de planning.

Waarom Hyvä in plaats van het standaard Luma-thema?

Luma sleept de RequireJS- en Knockout-frontend van Magento mee, en dat is het trage deel. Hyvä vervangt dat door Tailwind en Alpine, dus een rebuild van zes weken levert standaard een snelle PDP.

Kunnen we elke URL van de oude shop behouden?

Bijna altijd. De Data Migration Tool plus een diff tegen de nieuwe url_rewrite-tabel vangt mismatches op, en de restlijst gaat als permanente 301-regels in nginx vóór de DNS-flip.

Hoe voorkom je gedwongen wachtwoord-resets voor terugkerende klanten?

De Data Migration Tool zet de hashes van klantwachtwoorden over. Magento 2 rehasht bij de eerste succesvolle login, transparant. Er gaat geen reset-mail uit, maar je moet het login-pad wel load-testen.

Wat is het grootste risico in de cutover-nacht?

Payment-integraties. PSP-modules voor Hyvä Checkout worden soms uitgeleverd met edge-case-bugs die alleen op één bank of één device afgaan. Test elke methode met een echte kaart vóór cutover, niet erna.

magentomigrationlegacy sitese-commercephpcase study

Iets bouwen?

Start een project