MongoDB naar Postgres

OPMERKING: Dit blogbericht is een samenvoeging van mijn MongoDB naar Postgres (2024-03-06) en Sequelize vs. Prisma (2023-05-25). De oorspronkelijke blogs zijn verwijderd, en dit blog heeft hun plaats ingenomen, omdat beide in wezen dezelfde inhoud/informatie bevatten. De migratie begon begin maart 2023, de overstap vond plaats in half november 2023, en alle instanties van het oude MongoDB-systeem werden volledig afgesloten in begin januari 2024.

Inleiding

Tijdens mijn tijd bij eBay werd ik geconfronteerd met wat het meest technisch uitdagende probleem van mijn carrière zou worden: het migreren van het Storage Management System (STMS) van MongoDB naar Postgres. Dit was niet zomaar een eenvoudige databasewissel; het was een complete architecturale transformatie van een kritisch systeem dat meer dan 1,5 miljoen metingen per minuut verwerkt verspreid over de datacenters van eBay, met de vereiste van zero downtime en het behouden van vrijwel alle bestaande functionaliteit.

Wat is STMS?

Het Storage Management System (STMS) dient als een cruciaal intern hulpmiddel voor het team Service & Storage Infrastructure (SSI) van eBay. Het monitort en beheert apparaten verspreid over de datacenters van eBay, waardoor engineers kunnen:

  • Metingen van tientallen arrays, switches, hosts, diskgroepen en clusters monitoren
  • Waarschuwingen voor switches en arrays afhandelen
  • Geavanceerde taken zoals hosttoewijzingen voltooien
  • Toegang krijgen tot realtimegegevens voor andere interne eBay-services

STMS is verantwoordelijk voor meer dan 70 arrays, 60 switches, 1100 hosts, 900 diskgroepen en 200 clusters verspreid over 3 datacenters van eBay. Gezien zijn vitale rol in de infrastructuur van eBay zou elke downtime of verlies van functionaliteit rechtstreeks invloed hebben op de kernservices en bedrijfsactiviteiten van het bedrijf.

De uitdaging

Waarom de migratie nodig was

De beslissing om van MongoDB naar Postgres te migreren werd niet lichtvaardig genomen. Hoewel MongoDB STMS in eerste instantie goed had bediend, maakten de toenemende complexiteit van onze datarelatie en de behoefte aan geavanceerdere querymogelijkheden Postgres tot een betere langetermijnoplossing voor onze use case.

Waarom dit probleem moeilijk was

De complexiteit van deze migratie kwam voort uit verschillende fundamentele uitdagingen:

1. Fundamentele databaseverschillen MongoDB en Postgres zijn fundamenteel verschillende databases. MongoDB is een documentgebaseerde database (NoSQL), wat betekent dat gegevens worden opgeslagen als JSON in collecties, zoals documenten in een archiefkast. Postgres is een relationele database (SQL), wat betekent dat gegevens worden opgeslagen als rijen in tabellen, zoals in een spreadsheet.

2. Architectuur van de codebase De volledige backend van STMS was gebouwd om gegevens te verwerken en te beheren als JSON’s, met uitsluitend MongoDB-compatibele packages voor databasebewerkingen. Dit betekende niet alleen de database veranderen, maar ook herstructureren hoe onze volledige applicatie gegevens afhandelde.

3. Vereiste van zero downtime Vanwege hoe belangrijk STMS is als intern hulpmiddel, kon er tijdens de migratie geen downtime zijn. Het systeem moest gedurende het hele proces 1,5+ miljoen metingen per minuut blijven verwerken.

4. Strakke tijdlijn & beperkte ervaring De migratie moest binnen een paar maanden worden voltooid, zonder aanvankelijk duidelijk uitvoeringsplan. Noch ik, noch mijn collega’s hadden ervaring met het migreren van een grote legacy-codebase van NoSQL- naar SQL-databases, en ik had beperkte eerdere ervaring met Postgres.

5. Schaal & complexiteit De migratie omvatte het omzetten van 36 MongoDB-collecties naar 74 Postgres-tabellen, wat zorgvuldige afweging vereiste van relaties, indexering en query-optimalisatie.

De juiste ORM kiezen: Sequelize vs Prisma

Een van de eerste belangrijke beslissingen was het selecteren van een ORM (Object-Relational Mapping)-tool. Omdat onze codebase al was ontworpen om Mongoose voor MongoDB te gebruiken, zou het gebruik van een ORM de soepelste overgangsroute bieden.

Analyse van de vereisten

Na zorgvuldige analyse van de behoeften van het project stelde ik essentiële criteria vast voor elke ORM-oplossing:

  • Moet een JavaScript-package zijn (het grootste deel van onze code was geschreven in JavaScript)
  • Moet Postgres en de meeste van zijn functies ondersteunen
  • Prestaties moeten minstens gelijk zijn aan of beter zijn dan Mongoose
  • Moet open source zijn en onderhouden worden

De kandidaten

Na uitgebreid onderzoek beperkte ik me tot twee belangrijkste kanshebbers: Sequelize en Prisma. Ik creëerde uitgebreide testomgevingen met behulp van Docker voor Postgres en zette onze grootste, meest complexe dataset om van documentstructuur naar tabelstructuur.

Testmethodologie

Voor elke ORM mat ik de prestaties over kritieke bewerkingen:

  • Tijd om een invoer te maken
  • Tijd om een invoer bij te werken
  • Tijd om geneste invoeren bij te werken (relaties en JSON-sleutel-waarden)
  • Tijd om een invoer te verwijderen
  • Tijd om een invoer op te vragen/op te halen

De beslissing: Sequelize

Rond 15 mei 2023 besloot ik dat Sequelize de betere ORM was voor onze use case. Dit is waarom:

Voordelen van Sequelize:

  • Echt open source en niet onderhouden door een gefinancierde startup
  • Ondersteunde de meeste functies van Postgres
  • Betere prestaties, vooral vergeleken met Prisma
  • Volwassen ecosysteem met meer dan 10 jaar ontwikkeling
  • Flexibele model/schema-representatie met behulp van JavaScript-klassen
  • Ondersteuning voor complexe joins en filteropties, inclusief Regex

Prestatieresultaten:

In mijn tests presteerde Sequelize aanzienlijk beter dan Prisma. Voor onze invoeren van de grote dataset:

  • Sequelize: ~2,26 seconden per invoer
  • Prisma: ~11,21 seconden per invoer

Prisma was ongeveer 5x langzamer dan Sequelize voor onze use case. Bovendien duurde het verwijderen van één invoer uit onze grootste dataset bij Prisma bijna 4 minuten, wat onaanvaardbaar was voor onze vereisten.

Uitdagingen van Sequelize:

  • Complexere en opgeblazen modelrepresentaties (564 regels vs 262 regels voor Mongoose)
  • Verwarrende syntaxis in bepaalde gevallen
  • Complexiteit van database-migratie
  • Minder uitgebreide documentatie in vergelijking met Prisma

Voor- en nadelenvergelijking van Sequelize & Prisma

Om een vollediger beeld te geven van waarom ik voor Sequelize koos, wil ik de gedetailleerde voor- en nadelen delen die ik tijdens mijn evaluatie voor beide ORM’s heb samengesteld. Ik heb ook gekeken naar hoe ze zich verhoudingen in termen van schemarepresentatie en community-ondersteuning per 15 mei 2023. Deze diepere duik hielp mijn keuze te verstevigen, en ik hoop dat het nuttig kan zijn voor iedereen die met een vergelijkbare beslissing wordt geconfronteerd.

Voordelen van Sequelize:

  • Heeft een sync()-functie die automatisch tabellen voor je aanmaakt en beheert, wat veel handmatig werk bespaart.
  • Kan complexe joins voor geneste gegevens afhandelen, wat cruciaal was voor de structuur van STMS.
  • Ondersteunt een breed scala aan filteropties, inclusief Regex, wat flexibiliteit biedt in queries.
  • Model/schema-representatie gebeurt in ruwe JavaScript met behulp van klassen, die sterk aanpasbaar zijn om aan specifieke behoeften te voldoen.
  • Behandelt databaseverbindingen naadloos, inclusief ondersteuning voor meerdere read-verbindingen.
  • Ondersteunt ruwe SQL-query’s wanneer je onder de motorkap moet kijken.
  • Communitystatistieken per 15 mei 2023: Op NPM, laatst bijgewerkt 14 dagen geleden met 1.505.835 wekelijkse downloads; op GitHub, laatst bijgewerkt gisteren met 4,2k forks en 27,9k sterren. Het is al meer dan 10 jaar open source met een MIT-licentie, dus ik ben ervan overtuigd dat dat zo zal blijven.

Nadelen van Sequelize:

  • Model/schema-representatie kan erg complex en opgeblazen worden. Zo was de Mongoose-representatie van onze grote dataset ongeveer 262 regels (inclusief spaties), terwijl dezelfde dataset in Sequelize uitgroeide tot 564 regels.
  • De syntaxis kan in bepaalde scenario’s verwarrend en ingewikkeld zijn, wat me soms vertraagde.
  • Migreren of bewerken van de database is omslachtig. Zelfs met sequelize-cli dat migratiescripts genereert, blijft het lastig, hoewel ik heb gemerkt dat dit een veelvoorkomend pijnpunt is bij de meeste ORM’s.
  • Documentatie is niet geweldig, hoewel deze verbetert. Gelukkig hebben tools zoals ChatGPT een solide begrip van Sequelize vanwege de lange geschiedenis ervan, wat hielp de hiaten op te vullen.
  • Niet zo typesensitief als Prisma, wat in sommige projecten tot problemen kan leiden.
  • Beperkte TypeScript-ondersteuning, hoewel dit voor STMS geen probleem was, kan het voor anderen een breekpunt zijn.

Voordelen van Prisma:

  • Gebruikt zijn eigen schemataal, waardoor het maken van modellen netter en beknopter is. Ter vergelijking: terwijl Mongoose 262 regels nodig had voor onze grote dataset, deed Prisma het in slechts 221 regels.
  • Wordt geleverd met een CLI-tool die het maken en migreren van databases vereenvoudigt, wat tot nu toe het beste is dat ik van een ORM heb gezien, ook al is het niet perfect.
  • Ondersteunt ruwe SQL-query’s en biedt flexibiliteit wanneer nodig.
  • De codesyntaxis is overzichtelijk en eenvoudiger te begrijpen in vergelijking met Sequelize, waardoor het makkelijker te leren is.
  • Genereert automatisch query builders voor Node.js en TypeScript via zijn client, wat een mooie toevoeging is.
  • Heeft uitstekende, overzichtelijke documentatie. ChatGPT is niet zo up-to-date over Prisma, maar de officiële docs maakten dat vaak goed.
  • Communitystatistieken per 15 mei 2023: Op NPM, laatst bijgewerkt 6 dagen geleden met 1.344.705 wekelijkse downloads; op GitHub, laatst bijgewerkt 3 uur geleden met 1,1k forks en 31,3k sterren.

Nadelen van Prisma:

  • Ondersteunt geen Regex-filtering voor Postgres, hoewel het alternatieven biedt zoals “contains”, “includes” en “startsWith.”
  • Prestaties waren een groot probleem in mijn tests. Het maken van invoeren voor onze grote dataset kostte Prisma ongeveer 11,21 seconden per invoer vergeleken met Sequelize’s 2,26 seconden, ongeveer 5x langzamer.
  • Het verwijderen van één enkele invoer uit de grote dataset duurde bijna 4 minuten, wat voor onze behoeften een afknapper was.
  • Zelfs met een eerlijke vergelijking op een complexe, drielaags diepe relationele dataset was Sequelize aanzienlijk sneller bij verwijderingen.
  • Prisma wordt gesteund door een startup met $56,5 miljoen aan financiering. Hoewel de hoofd-ORM-code open source is onder Apache-2.0, ben ik beducht voor mogelijke licentiewijzigingen verderop, vergelijkbaar met wat er met MongoDB is gebeurd.

Deze gedetailleerde vergelijkingen maakten duidelijk dat Sequelize beter aansloot bij de behoeften van STMS, vooral op het gebied van prestaties en betrouwbaarheid op de lange termijn. Maar ik dacht dat het zo uitsplitsen anderen misschien kon helpen die voor dezelfde keuze stonden voor hun projecten.

Het migratieproces

Transformatie van de datastructuur

Het omzetten van de documentstructuur van MongoDB naar de relationele structuur van Postgres vereiste zorgvuldige planning. Ik moest:

  1. Relaties analyseren: Vaststellen hoe MongoDB-documenten zich tot elkaar verhielden en passende foreign-keyrelaties ontwerpen
  2. Gegevens normaliseren: Geneste documenten opsplitsen in afzonderlijke tabellen waar passend
  3. JSON-functies behouden: JSONB-kolommen gebruiken voor echt ongestructureerde gegevens die flexibel moesten blijven
  4. Indexen ontwerpen: Passende indexen maken voor queryprestaties

Aangepaste oplossingen

De migratie vereiste de ontwikkeling van verschillende aangepaste oplossingen:

1. Gegevensmigratiescripts Ik maakte uitgebreide scripts om:

  • Gegevens uit MongoDB-collecties te extraheren
  • Documentstructuren om te zetten naar een relationeel formaat
  • Gegevens met juiste relaties in Postgres-tabellen te importeren

2. Compatibiliteitslaag voor de API Om zero downtime te behouden, bouwde ik een compatibiliteitslaag die kon:

  • Verzoeken routeren naar MongoDB of Postgres, afhankelijk van de migratiestatus
  • Gegevensconsistentie tijdens de overgangsperiode waarborgen
  • Terugvalmechanismen bieden

3. Aangepaste middleware Middleware ontwikkeld om de verschillen in de manier waarop MongoDB en Postgres bepaalde bewerkingen afhandelen te verwerken, zodat bestaande API-endpoints zonder wijziging bleven werken.

Technische uitdagingen overwinnen

Omgaan met complexe relaties

Een van de grootste uitdagingen was het omzetten van de ingebedde documenten van MongoDB naar Postgres-relaties. Een enkel MongoDB-document kon bijvoorbeeld bevatten:

  • Basiskenmerken
  • Geneste objecten die gerelateerde entiteiten vertegenwoordigen
  • Arrays van ingebedde documenten

Dit moest zorgvuldig worden ontleed in:

  • Hoofdtabel(len) voor hoofdentiteiten
  • Koppeltabellen voor many-to-many-relaties
  • Foreign-keyrelaties voor one-to-many-associaties

Query-optimalisatie

De querypatronen van MongoDB vertalen zich niet rechtstreeks naar SQL. Ik moest:

  • Complexe aggregatiepipelines herschrijven als SQL-joins
  • Indexen optimaliseren voor nieuwe querypatronen
  • Zorgen dat de queryprestaties gelijk waren aan of beter waren dan die van MongoDB

Gegevensintegriteit

Het waarborgen van gegevensintegriteit tijdens de migratie vereiste:

  • Uitgebreide validatiescripts
  • Terugdraai-procedures
  • Real-time datasynchronisatie tijdens overgangsperiodes

Resultaten & impact

De STMS-migratie van MongoDB naar Postgres is succesvol voltooid zonder downtime en met behoud van vrijwel alle functies en functionaliteit. De resultaten overtroffen de verwachtingen:

Prestatieverbeteringen:

  • Queryprestaties verbeterd voor complexe relationele queries
  • Betere gegevensconsistentie en integriteit
  • Efficiënter gebruik van opslag

Operationele voordelen:

  • Verbeterde monitoring- en foutopsporingsmogelijkheden
  • Betere integratie met eBay’s bestaande SQL-gebaseerde tools
  • Verbeterde back-up- en herstelprocedures

Impact op het team:

  • Meer kennis binnen het team van relationele databases
  • Patronen vastgesteld voor toekomstige database-migraties
  • Herbruikbare tools en processen gecreëerd

Verworven technische vaardigheden

Dit project heeft mijn technische expertise aanzienlijk uitgebreid:

Databasetechnologieën:

  • Diepgaand begrip van Postgres-functies en optimalisatie
  • SQL-queryoptimalisatie en prestatieafstemming
  • Databaseontwerppatronen en normalisatie
  • Primary-standby-databaseconfiguraties

Ontwikkeltools:

  • Sequelize ORM en query-opbouw
  • Database-migratiestrategieën
  • Methodologieën voor prestatietests
  • Gegevensvalidatie en integriteitscontrole

Architectuurpatronen:

  • Zero-downtime-migratiestrategieën
  • Compatibiliteitslagen voor API’s
  • Database-abstraheringspatronen
  • Monitoring- en waarschuwingssystemen

Persoonlijke en professionele groei

Dit migratieproject was transformerend voor mijn loopbaanontwikkeling. Het duwde me in onbekend terrein, wat het volgende vereiste:

Leiderschapsvaardigheden:

  • Het leiden van een complex technisch project zonder eerdere ervaring
  • Kritieke architecturale beslissingen nemen onder druk
  • Coördineren met meerdere teams en belanghebbenden

Probleemoplossend vermogen:

  • Complexe problemen opsplitsen in beheersbare componenten
  • Creatieve oplossingen ontwikkelen voor ongekende uitdagingen
  • Meerdere concurrerende vereisten en beperkingen in balans brengen

Communicatie & teamwork:

  • Technische concepten uitleggen aan niet-technische belanghebbenden
  • Processen en beslissingen documenteren voor toekomstige raadpleging
  • Teamleden begeleiden bij nieuwe technologieën en patronen

Geleerde lessen

Technische lessen

  1. Databaseselectie is belangrijk: De keuze tussen NoSQL en SQL moet gebaseerd zijn op specifieke use cases en langetermijnvereisten
  2. Prestatietests zijn cruciaal: Theoretische voordelen vertalen zich niet altijd naar prestatieverbeteringen in de praktijk
  3. Migratieplanning: Uitgebreide planning en tests zijn essentieel voor complexe migraties
  4. Investeren in tooling: Het vooraf bouwen van goede tooling bespaart aanzienlijk veel tijd en vermindert fouten

Lessen in projectmanagement

  1. Communicatie met belanghebbenden: Regelmatige updates en duidelijke communicatie voorkomen misverstanden
  2. Risicobeheer: Het hebben van fallback-plannen en rollback-procedures is essentieel
  3. Tijdlijnbeheer: Reserveer buffer-tijd voor onverwachte uitdagingen en leercurves
  4. Documentatie: Grondige documentatie maakt kennisoverdracht en toekomstig onderhoud mogelijk

Conclusie

De STMS-migratie van MongoDB naar Postgres is mijn meest uitdagende en lonende technische probleemoplossing uit mijn loopbaan. Het vereiste niet alleen technische expertise, maar ook leiderschap, planning en aanpassingsvermogen. Het succes van het project liet zien dat zelfs de meest complexe technische uitdagingen kunnen worden overwonnen met de juiste planning, grondige tests en toewijding aan uitmuntendheid.

Deze ervaring heeft mijn benadering van software engineering fundamenteel veranderd en benadrukt het belang van:

  • De volledige context en vereisten begrijpen voordat technische beslissingen worden genomen
  • Tijd investeren in goede tooling en tests
  • Duidelijke communicatie behouden gedurende complexe projecten
  • Bereid zijn nieuwe technologieën en benaderingen te leren wanneer dat nodig is

Het succes van de migratie verbeterde niet alleen de mogelijkheden van STMS, maar vestigde ook patronen en processen die nog steeds bijdragen aan eBay’s infrastructuurprojecten. Het versterkte mijn overtuiging dat het omarmen van onbekende uitdagingen en daarin slagen essentieel is voor zowel persoonlijke als professionele ontwikkeling.

Terugkijkend vertegenwoordigt dit project een keerpunt in mijn loopbaan, waarbij ik veranderde van een ontwikkelaar die oplossingen implementeert in een engineer die complexe technische initiatieven kan ontwerpen en leiden. Het vertrouwen en de vaardigheden die uit deze ervaring zijn voortgekomen, blijven mijn aanpak van nieuwe uitdagingen en kansen in software engineering sturen.