Databases blijven vaak decennia meegaan terwijl apps herschreven worden. Lees waarom gegevens blijven bestaan, waarom migraties kostbaar zijn en hoe je schema's ontwerpt die veilig kunnen evolueren.

Als je al een paar jaar met software werkt, heb je waarschijnlijk hetzelfde verhaal vaker gezien: de app wordt opnieuw ontworpen, herschreven, rebranded — of volledig vervangen — terwijl de database stilletjes door blijft draaien.
Een bedrijf kan van een desktop-app naar een webapp gaan, vervolgens naar mobiel, en dan naar een “v2” gebouwd met een nieuw framework. Toch staan klantgegevens, bestellingen, facturen en het productcatalogus vaak nog steeds in dezelfde database (of een directe afstammeling daarvan), soms met tabellen die tien jaar geleden zijn aangemaakt.
Eenvoudig gezegd: applicatiecode is de interface en het gedrag, en die verandert vaak omdat het relatief makkelijk is om te vervangen. De database is het geheugen, en die veranderen is riskant omdat hij de geschiedenis bewaart waarop het bedrijf vertrouwt.
Een simpel niet-technisch voorbeeld: je kunt een winkel renoveren — nieuwe schappen, nieuwe kassa’s, nieuwe bewegwijzering — zonder de voorraadadministratie en bonnetjes weg te gooien. De renovatie is de app. De administratie is de database.
Als je dit patroon eenmaal ziet, verandert het hoe je beslissingen neemt:
In de volgende secties leer je waarom databases blijven bestaan, wat data moeilijker maakt om te verplaatsen dan code, en praktische manieren om schema’s en operatie zó in te richten dat ze meerdere applicatieherschrijvingen kunnen overleven — zonder dat elke wijziging een crisis wordt.
Applicaties voelen als het “product”, maar de database is waar het product zich herinnert wat er is gebeurd.
Een shopping-app kan vijf keer worden herontworpen, maar klanten verwachten nog steeds dat hun aankoopgeschiedenis er is. Een supportportaal kan van leverancier wisselen, maar de registratie van tickets, terugbetalingen en gemaakte beloften moet consistent blijven. Die continuïteit leeft in opgeslagen data: klanten, bestellingen, facturen, abonnementen, events en de relaties daartussen.
Als een feature verdwijnt, zijn gebruikers geïrriteerd. Als data verdwijnt, kun je vertrouwen, omzet en juridische grond verliezen.
Een app kan vaak opnieuw worden opgebouwd uit versiebeheer en documentatie. De echte geschiedenis kun je niet “opnieuw draaien”. Je kunt vorig jaar’s betalingen niet opnieuw laten plaatsvinden, iemands gegeven toestemming op dat moment niet precies reproduceren, of exact reconstrueren wat er wanneer is verzonden. Zelfs gedeeltelijk verlies — ontbrekende tijdstempels, verweesde records, inconsistente totalen — kan het product onbetrouwbaar doen aanvoelen.
De meeste data wordt nuttiger naarmate die langer bestaat:
Daarom behandelen teams data als een asset, niet als bijproduct. Een verse applicatieherschrijving levert misschien een betere UI, maar vervangt zelden jaren aan historische waarheid.
In de loop van de tijd standaardiseren organisaties ongemerkt op de database als gedeeld referentiepunt: geëxporteerde spreadsheets daaruit, dashboards erop gebouwd, financiële processen erop afgestemd en “known-good” queries die terugkerende vragen beantwoorden.
Dat is het emotionele hart van databaselevensduur: de database wordt het geheugen waar iedereen op vertrouwt — zelfs als de applicatie eromheen blijft veranderen.
Een database is zelden “in eigendom” van één enkele applicatie. In de loop van de tijd wordt het de gedeelde bron van waarheid voor meerdere producten, interne tools en teams. Die gedeelde afhankelijkheid is een belangrijke reden waarom databases blijven bestaan terwijl applicatiecode wordt vervangen.
Het komt vaak voor dat één set tabellen dient voor:
Elk van deze consumenten kan in andere talen zijn gebouwd, op andere schema’s worden vrijgegeven en door verschillende mensen worden onderhouden. Als een applicatie wordt herschreven, kan die snel zijn eigen code aanpassen — maar hij moet nog steeds dezelfde records lezen en bewaren waarop iedereen anders vertrouwt.
Integraties „binden” zich vaak aan een bepaald datamodel: tabelnamen, kolombetekenissen, referentie-IDs en aannames over wat een record vertegenwoordigt. Zelfs als de integratie technisch via een API verloopt, weerspiegelt de API vaak het onderliggende databasemodel.
Daarom is het wijzigen van de database geen een-team-beslissing. Een schemawijziging kan exports, ETL-jobs, rapportagequeries en downstream-systemen raken die niet eens in de hoofdproduct-repo zitten.
Als je een bug in een feature uitrolt, rol je die terug. Als je een gedeeld databasecontract breekt, kun je facturatie, dashboards en rapportage tegelijk onderbreken. Het risico wordt vermenigvuldigd met het aantal afhankelijken.
Dit is ook waarom “tijdelijke” keuzes (een kolomnaam, een enum-waarde, een eigenzinnige betekenis van NULL) kleverig worden: te veel dingen hangen stilletjes aan hen.
Als je praktische strategieën wilt voor veilig beheer, zie /blog/schema-evolution-guide.
Code herschrijven kan vaak in delen gebeuren. Je kunt een UI wisselen, een service vervangen of een feature achter een API herbouwen terwijl je dezelfde database behoudt. Als er iets misgaat, kun je een deploy terugdraaien, verkeer terugleiden naar het oude module of oude en nieuwe code naast elkaar draaien.
Data geeft je die flexibiliteit niet. Data is gedeeld, onderling verbonden en wordt meestal verwacht correct te zijn op elk moment — niet “grotendeels correct na de volgende deploy.”
Als je code refactort, verander je instructies. Als je data migreert, verander je het ding waarop het bedrijf vertrouwt: klantrecords, transacties, audittrails, productgeschiedenis.
Een nieuwe service kan op een subset van gebruikers worden getest. Een nieuwe databasemigratie raakt alles: huidige gebruikers, oude gebruikers, historische rijen, verweesde records en vreemde éénmalige items veroorzaakt door een bug van drie jaar geleden.
Een datamigratie is niet zomaar "exporteren en importeren." Het omvat meestal:
Elke stap heeft verificatie nodig, en verificatie kost tijd — vooral wanneer de dataset groot is en de gevolgen van een fout groot.
Code-deploys kunnen frequent en omkeerbaar zijn. Datacutovers zijn meer als een operatie.
Als je downtime nodig hebt, coördineer je bedrijfsvoering, support en klantverwachtingen. Als je streeft naar nagenoeg geen downtime, doe je waarschijnlijk dual-writes, change data capture of zorgvuldig gefaseerde replicatie — plus een plan voor wat er gebeurt als het nieuwe systeem trager of onjuist is.
Rollbacks zijn ook anders. Terugdraaien van code is eenvoudig; data terugzetten betekent vaak backups herstellen, wijzigingen opnieuw afspelen, of accepteren dat sommige schrijfacties op de “verkeerde” plek zijn gebeurd en moeten worden verzoend.
Databases verzamelen geschiedenis: vreemde records, legacy-statussen, deels gemigreerde rijen en workarounds die niemand zich herinnert. Deze randgevallen verschijnen zelden in een ontwikkeldataset, maar komen direct naar boven tijdens een echte migratie.
Daarom accepteren organisaties vaak het herschrijven van code (zelfs meerdere keren) terwijl de database stabiel blijft. De database is niet zomaar een afhankelijkheid — het is het moeilijkste om veilig te veranderen.
Een wijziging in applicatiecode gaat meestal over het uitrollen van nieuw gedrag. Als er iets misgaat, kun je een deployment terugdraaien, feature-flags gebruiken of snel patchen.
Een schemawijziging is anders: die herschikt de regels voor data die al bestaat, en die data kan jaren oud, inconsistent of door meerdere services en rapporten gebruikt zijn.
Goede schema’s blijven zelden bevroren. De uitdaging is ze te laten evolueren terwijl historische data geldig en bruikbaar blijft. In tegenstelling tot code kun je data niet “hercompileren” naar een schone staat — je moet elke oude rij meenemen, inclusief randgevallen die niemand zich herinnert.
Daarom neigt schema-evolutie naar wijzigingen die bestaande betekenissen behouden en vermijden dat bestaande opslag een volledige herschrijving afdwingt.
Additieve wijzigingen (nieuwe tabellen, nieuwe kolommen, nieuwe indexen) laten meestal oude code blijven werken terwijl nieuwe code van de nieuwe structuur profiteert.
Brekende wijzigingen — een kolom hernoemen, een type veranderen, één veld in meerdere opsplitsen, constraints aanscherpen — vereisen vaak gecoördineerde updates in:
Zelfs als je de hoofdapp bijwerkt, kan een vergeten rapport of integratie stilletjes afhankelijk zijn van de oude vorm.
"Gewoon het schema wijzigen" klinkt simpel totdat je miljoenen bestaande rijen moet migreren terwijl het systeem online blijft. Je moet nadenken over:
NOT NULL kolommenALTER-operatiesIn veel gevallen eindig je met meerstapsmigraties: voeg nieuwe velden toe, schrijf naar beide, backfill, schakel reads om en retireer oude velden later.
Codewijzigingen zijn omkeerbaar en geïsoleerd; schemawijzigingen zijn duurzaam en gedeeld. Zodra een migratie is uitgevoerd, wordt het deel van de databasegeschiedenis — en elke toekomstige productversie moet met die beslissing leven.
Applicatieframeworks cyclusseren snel: wat vijf jaar geleden “modern” leek, kan nu niet meer ondersteund, ongebruikelijk of moeilijk in te huren zijn. Databases veranderen ook, maar veel kernideeën — en dagelijkse vaardigheden — bewegen veel langzamer.
SQL en relationele concepten zijn opmerkelijk stabiel gebleven gedurende decennia: tabellen, joins, constraints, indexen, transacties en query-plannen. Vendors voegen features toe, maar het mentale model blijft herkenbaar. Die stabiliteit betekent dat teams een applicatie in een nieuwe taal kunnen herschrijven en toch hetzelfde onderliggende datamodel en query-gedrag kunnen behouden.
Zelfs nieuwere databaseproducten behouden vaak deze vertrouwde queryconcepten. Je ziet “SQL-achtige” querylagen, relationele joins of transactionele semantiek opnieuw opduiken omdat ze goed mapten op rapportage, troubleshooten en zakelijke vragen.
Omdat de basis consistent blijft, persisteert het ecosysteem over generaties heen:
Deze continuïteit vermindert geforceerde herschrijvingen. Een bedrijf kan een app-framework laten varen omdat inhuren stopt of security-updates wegvallen, maar zelden SQL als gedeelde taal voor data.
Database-standaarden en conventies creëren een gemeenschappelijke basis: SQL-dialecten zijn niet identiek, maar ze lijken meer op elkaar dan de meeste webframeworks. Dat maakt het makkelijker om een database stabiel te houden terwijl de applicatielaag evolueert.
Het praktische effect is eenvoudig: wanneer teams een applicatieherschrijving plannen, kunnen ze vaak bestaande databasevaardigheden, querypatronen en operationele praktijken behouden — waardoor de database de stabiele fundering wordt die meerdere generaties code overleeft.
De meeste teams blijven niet bij dezelfde database omdat ze er dol op zijn. Ze blijven omdat ze een werkend stel operationele gewoonten hebben opgebouwd — en die gewoonten zijn met moeite verworven.
Zodra een database in productie is, wordt het onderdeel van de altijd-aan-machinerie van het bedrijf. Het is het ding waarvoor mensen om 2 uur ’s nachts worden gebeld, het ding waar audits naar vragen en het ding waar elke nieuwe service uiteindelijk mee moet praten.
Na een jaar of twee hebben teams meestal een betrouwbaar ritme:
Het vervangen van de database betekent al die kennis opnieuw leren onder echte load, met echte klantverwachtingen.
Databases zijn zelden "instellen en vergeten". In de loop van de tijd bouwt het team een catalogus van betrouwbaarheidservaring op:
Die kennis leeft vaak in dashboards, scripts en mensen’s hoofd — niet in één document. Een herschrijving van applicatiecode kan gedrag behouden terwijl de database blijft dienen. Een databasevervanging dwingt je om gedrag, performance en betrouwbaarheid tegelijk opnieuw op te bouwen.
Beveiliging en toegangscontroles zijn centraal en langdurig. Rollen, permissies, auditlogs, secret-rotatie, encryptie-instellingen en “wie wat kan lezen” sluiten vaak aan op compliance-eisen en interne policies.
Het veranderen van de database betekent het herdoen van toegangsmodellen, het opnieuw valideren van controls en het opnieuw aantonen aan het bedrijf dat gevoelige data nog steeds beschermd is.
Operationele volwassenheid houdt de database op zijn plek omdat het risico verlaagt. Zelfs als een nieuwe database betere features belooft, heeft de oude iets krachtigs: een geschiedenis van up blijven, herstelbaar zijn en begrijpelijk blijven als er iets misgaat.
Applicatiecode kan worden vervangen door een nieuw framework of schonere architectuur. Complianceverplichtingen zijn echter gekoppeld aan records — wat er gebeurde, wanneer, wie het goedkeurde en wat de klant op dat moment zag. Daarom wordt de database vaak het onbewegende object bij een herschrijving.
Veel sectoren hebben minimumeisen voor het bewaren van facturen, toestemmingsrecords, financiële gebeurtenissen, supportinteracties en toegangslogs. Auditors accepteren meestal niet "we hebben de app herschreven" als reden om geschiedenis te verliezen.
Zelfs als je team een legacy-tabel niet meer dagelijks gebruikt, moet je die mogelijk op verzoek kunnen leveren, samen met uitleg over hoe deze is ontstaan.
Chargebacks, refunds, leveringsgeschillen en contractvragen hangen af van historische snapshots: de prijs destijds, het gebruikte adres, de geaccepteerde voorwaarden of de status op een specifiek moment.
Wanneer de database de gezaghebbende bron is van die feiten, is vervangen niet alleen een technisch project — het loopt het risico bewijs aan te tasten. Daarom houden teams vaak de bestaande database en bouwen ze nieuwe services eromheen in plaats van "migreren en hopen dat het overeenkomt."
Sommige records mogen niet worden verwijderd; andere mogen niet op manieren worden getransformeerd die traceerbaarheid breken. Als je denormaliseert, velden samenvoegt of kolommen verwijdert, verlies je mogelijk het vermogen om een audittrail te reconstrueren.
Deze spanning is vooral zichtbaar wanneer privacyvereisten met retentie botsen: je hebt mogelijk selectieve redaction of pseudonimisering nodig terwijl je transacties nog steeds intact houdt. Die beperkingen leven meestal het dichtst bij de data.
Dataclassificatie (PII, financieel, gezondheid, intern) en governancebeleid blijven vaak stabiel, zelfs als producten evolueren. Toegangscontroles, rapportagedefinities en beslissingen over "single source of truth" worden gewoonlijk op databaseniveau gehandhaafd omdat veel tools erop vertrouwen: BI-dashboards, finance-exports, rapporten aan toezichthouders en incidentonderzoeken.
Als je een herschrijving plant, behandel compliance-rapportage als eerste-klasse vereiste: inventariseer vereiste rapporten, retentieschema’s en audit-velden voordat je schema’s aanraakt. Een eenvoudige checklist kan helpen (zie /blog/database-migration-checklist).
De meeste “tijdelijke” databasekeuzes worden niet gedachteloos gemaakt — ze zijn genomen onder druk: een lanceringsdeadline, een dringende klantvraag, een nieuwe regelgeving, een rommelige import. Het verrassende is hoe zelden die keuzes worden teruggedraaid.
Applicatiecode kan snel worden gerefactord, maar databases moeten vaak oude en nieuwe consumenten tegelijk bedienen. Legacy-tabellen en kolommen blijven omdat er iets afhankelijk van is:
Zelfs als je een veld hernoemt, laat je het vaak ook staan. Een veelvoorkomend patroon is het toevoegen van een nieuwe kolom (bijv. customer_phone_e164) terwijl phone voorlopig blijft omdat een nachtelijke export er nog steeds gebruik van maakt.
Workarounds worden ingebed in spreadsheets, dashboards en CSV-exports — plekken die zelden worden behandeld als productcode. Iemand bouwt een omzetrapport dat een verouderde tabel join't "tot Finance gemigreerd is." Dan gaat het kwartaalproces van Finance ervan afhangen, en het verwijderen van die tabel wordt een bedrijfsrisico.
Daarom kunnen verouderde tabellen jaren overleven: de database dient niet alleen de app; hij bedient de gewoonten van de organisatie.
Een veld toegevoegd als snelle fix — promo_code_notes, legacy_status, manual_override_reason — wordt vaak een beslissingspunt in workflows. Zodra mensen het gebruiken om uitkomsten te verklaren ("We hebben deze bestelling goedgekeurd omdat..."), is het niet langer optioneel.
Als teams een migratie niet vertrouwen, houden ze "shadow"-kopieën bij: gedupliceerde klantnamen, gecachte totalen of fallback-flags. Deze extra kolommen lijken onschuldig, maar creëren concurrerende bronnen van waarheid — en nieuwe afhankelijkheden.
Als je deze val wilt vermijden, behandel schema-wijzigingen als productwijzigingen: documenteer intentie, plan deprecations en traceer consumenten voordat je iets verwijdert. Voor een praktische checklist, zie /blog/schema-evolution-checklist.
Een database die meerdere app-generaties overleeft, moet minder worden behandeld als een interne implementatiedetail en meer als gedeelde infrastructuur. Het doel is niet elke toekomstige feature te voorspellen — het is verandering veilig, geleidelijk en omkeerbaar te maken.
Applicatiecode kan worden herschreven, maar datacontracten zijn moeilijker te heronderhandelen. Zie tabellen, kolommen en sleutelrelaties als een API waarop andere systemen (en toekomstige teams) zullen vertrouwen.
Geef de voorkeur aan additieve verandering:
Toekomstige herschrijvingen mislukken vaak niet omdat data ontbreekt, maar omdat het ambigu is.
Gebruik duidelijke, consistente naamgeving die intentie uitlegt (bijvoorbeeld billing_address_id vs. addr2). Ondersteun dat met constraints die regels coderen waar mogelijk: primary keys, foreign keys, NOT NULL, uniciteit en check-constraints.
Voeg lichte documentatie dicht bij het schema toe — kolom- en tabelcommentaar of een kort levend document in het interne handboek. “Waarom” is net zo belangrijk als “wat.”
Elke wijziging moet een pad vooruit en een pad terug hebben.
Een praktische manier om databasewijzigingen veiliger te houden tijdens frequente applicatie-iteraties is om "planning mode" en rollback-discipline in je delivery workflow te bakken. Bijvoorbeeld, wanneer teams interne tools of nieuwe app-versies bouwen op Koder.ai, kunnen ze itereren via chat terwijl ze het databaseschema als stabiel contract behandelen — gebruikmakend van snapshots en rollback-achtige praktijken om de impact van ongewilde wijzigingen te verkleinen.
Als je je database ontwerpt met stabiele contracten en veilige evolutie, worden applicatie-herschrijvingen routine in plaats van risicovolle datareddingsmissies.
Het vervangen van een database is zeldzaam, maar niet mythisch. Teams die het uitvoeren zijn niet per se "beter" — ze bereiden zich jaren eerder voor door data draagbaar te maken, afhankelijkheden zichtbaar te maken en de applicatie minder sterk te binden aan één engine.
Begin met exports te behandelen als een eersteklascapaciteit, niet als een eenmalig script.
Strakke koppeling verandert een migratie in een herschrijving.
Streef naar een gebalanceerde aanpak:
Als je snel een nieuwe service bouwt (bijv. een React-admin app plus een Go-backend met PostgreSQL), helpt het om een stack te kiezen die draagbaarheid en operationele duidelijkheid tot standaard maakt. Koder.ai leunt op die wijd geadopteerde primitieve en ondersteunt source code export — handig wanneer je de applicatielaag vervangbaar wilt houden zonder je datamodel aan een eenmalige tool te binden.
Databases voeden vaak meer dan de hoofdapp: rapporten, spreadsheets, geplande ETL-jobs, third-party integraties en auditpijplijnen.
Onderhoud een levend inventaris: wat leest/schrijft, hoe vaak en wat gebeurt er als het breekt. Zelfs een simpele pagina in /docs met eigenaren en contactpunten voorkomt onaangename verrassingen.
Veelvoorkomende signalen: licentie- of hostingbeperkingen, onoplosbare betrouwbaarheidproblemen, ontbrekende compliance-features of schaalgrenzen die extreem werk rond moeten maken.
Belangrijkste risico’s: dataverlies, subtiele betekenisverschillen, downtime en drift in rapportage.
Een veiligere aanpak is meestal parallel run: migreer continu data, valideer resultaten (aantallen, checksums, zakelijke metrics), verschuif verkeer geleidelijk en behoud een rollback-pad totdat het vertrouwen hoog is.
Omdat de database de historische waarheid van het bedrijf bewaart (klanten, bestellingen, facturen, audit trails). Code kan opnieuw worden uitgerold of herschreven; verloren of beschadigde geschiedenis is moeilijk te reconstrueren en kan financiële, juridische en vertrouwensproblemen veroorzaken.
Gegevenswijzigingen zijn gedeeld en duurzaam.
Een enkele database wordt vaak de gedeelde bron van waarheid voor:
Zelfs als je de applicatie herschrijft, vertrouwen al die consumenten nog steeds op stabiele tabellen, IDs en betekenissen.
Zelden. De meeste “migraties” zijn gefaseerd zodat het databasecontract stabiel blijft terwijl applicatiecomponenten veranderen.
Veelgebruikte aanpak:
De meeste teams streven naar additieve wijzigingen:
Dit laat oude en nieuwe code naast elkaar draaien tijdens de transitie.
Ambiguïteit blijft langer bestaan dan code.
Praktische stappen:
billing_address_id).NOT NULL, uniciteit, checks).Reken op de “vreemde” rijen.
Voor je migreert, plan voor:
Test migraties tegen productie-achtige data en neem verificatiestappen op, niet alleen transformatielogica.
Compliance kleeft aan records, niet aan de UI.
Je moet mogelijk bewaren en reproduceren:
Het hervormen of verwijderen van velden kan traceerbaarheid, rapportagedefinities of auditbaarheid breken — zelfs als de app al is vervangen.
Compatibiliteit creëert verborgen afhankelijkheden:
Behandel deprecations als productwijzigingen: documenteer intentie, track consumenten en stel terugtrekplannen op.
Een praktische checklist:
Dit maakt herschrijvingen routine in plaats van risicovolle “data rescue”-projecten.