Microservices vs monolit: sådan vælger du arkitektur til dit produkt

Microservices vs monolit: sådan vælger du arkitektur til dit produkt

Det korte svar: hvad skal du vælge nu?

Til de fleste nye produkter og danske teams er en monolit eller modulær monolit det klogeste udgangspunkt. Microservices giver først mening, når du har tydelige domænegrænser, flere autonome teams og et konkret behov for uafhængig deployment eller forskellig skalering. Start simpelt, mål dine problemer – og split først op, når du kan pege på dem.

Arkitektur Kode & deployment Skalering Drift & kompleksitet Typisk bedst til
Monolit Én kodebase, én deployment, ofte én database Skaleres samlet Lavest kompleksitet MVP, små teams, simple domæner
Modulær monolit Én deployment, opdelt i interne moduler/domæner Skaleres samlet, men med bedre struktur Middel kompleksitet Voksende produkter og teams
Microservices Flere selvstændige services med egne deployments Skaleres separat pr. service Høj kompleksitet Større systemer, flere autonome teams

Hvad er monolit og microservices – og hvad betyder det i praksis?

En monolit er typisk ét samlet system med én kodebase og én deployment, mens microservices opdeler produktet i flere selvstændigt deploybare services. For de fleste nye produkter er det enkleste og sikreste udgangspunkt en monolit eller modulær monolit, med microservices som et senere valg ved konkret behov.

I en klassisk monolit:

  • har du én kodebase, som alle arbejder i
  • bygger du typisk én applikation (eller få) og deployer alt samlet
  • bruger du ofte én database, som hele systemet taler med

Fordelen er enkelhed: ét build, ét deploy-flow, én logik at debugge ad gangen. Ulempen er, at alt hænger sammen – et lille change kan kræve ret meget regression test, og systemet skaleres som én blok.

I en microservices-arkitektur:

  • består systemet af flere små services med egen kodebase og ofte eget deploy-flow
  • taler services sammen via API’er eller events
  • har hver service typisk sit eget ansvar og ofte sit eget datalager

Fordelen er fleksibilitet: du kan deploye, skalere og udvikle services uafhængigt. Ulempen er distribueret kompleksitet: du får flere deployments, flere fejlscenarier, flere steder at lede, når noget går galt.

For et dansk produktteam betyder det i praksis:

  • Monolit: hurtigere i gang, enklere drift, mindre krav til specialiseret DevOps og observability.
  • Microservices: flere krav til CI/CD, logging, tracing og on-call, men bedre match, hvis du allerede har flere teams, der skal kunne rulle ud hver for sig.

Hvornår er en monolit det bedste valg?

En monolit er ofte det bedste valg, når teamet er lille, domænet stadig er under udvikling, og hurtig levering er vigtigere end maksimal fleksibilitet. Det giver lavere kompleksitet, enklere drift og bedre time-to-market i den tidlige fase.

Typiske tegn på, at en monolit giver mening:

  • Lille team – 1 til 8 udviklere, der arbejder tæt sammen.
  • Produktet er nyt – du er stadig ved at finde ud af, hvad der skal bygges.
  • Simpelt eller uklart domæne – forretningsregler ændrer sig ofte, eller er stadig til forhandling.
  • Få integrationer – måske et betalingsgateway, et CRM eller et mailsystem, men ikke 20 eksterne systemer.
  • Begrænset driftskapacitet – ingen fuldtids SRE/platformteam, måske bare “ham/hende der kan lidt DevOps”.

I en monolit:

  • er det lettere at holde data konsistente, fordi du ofte kan bruge én transaktion (klassiske ACID-transaktioner i databasen)
  • er debugging mere ligetil – du kan ofte genskabe flows lokalt uden at spinne 10 services op
  • er deployment mindre dramatisk – én pipeline, ét releasevindue

Monolit er ikke et “umodent” valg. Det er et rationelt valg, når:

  • du vil bygge en MVP hurtigt
  • du vil minimere koordinering og teknisk overhead
  • du hellere vil bruge tiden på features end på at bygge en avanceret platform

Hvis du vil strukturere koden ordentligt fra start, kan du kombinere monolitten med gode arkitekturprincipper og fx et simpelt systemudviklings-setup, i stedet for at gå direkte til microservices.

Hvornår giver microservices mening?

Microservices giver først rigtig mening, når systemet har klare domænegrænser, flere teams med reelt ejerskab og et konkret behov for uafhængig deployment eller separat skalering. Uden den organisatoriske og driftsmæssige modenhed bliver de ofte dyrere og mere komplekse end en monolit.

Praktiske kriterier, hvor microservices kan være forsvarlige:

  • Klare domæner – du kan pege på tydelige “bounded contexts” (fx betaling, katalog, brugerhåndtering), der stort set kan arbejde uafhængigt.
  • Flere teams – typisk 2 – 3+ teams, som du faktisk vil gøre autonome omkring hver deres domæne.
  • Behov for uafhængig deployment – fx mobilteamet skal kunne shippe ofte, uden at vente på alt andet.
  • Forskellige skaleringsprofiler – nogle dele af systemet kræver væsentligt mere kapacitet end andre (fx ordrebehandling ved spidsbelastninger).
  • CI/CD og drift på plads – I har allerede stabile pipelines, monitoring, alarmering og on-call-praksis.

Microservices løser typisk konkrete problemer som:

  • “vi kan ikke deploye uden at koordinere med tre andre teams hver gang”
  • “denne del af systemet går ofte i gulvet, når kampagner kører, men resten burde kunne fortsætte”
  • “ændringer ét sted breder sig hele vejen gennem kodebasen”

Men de introducerer også:

  • mere komplekse fejlsituationer på tværs af services
  • behov for stærkere observability (central logning, metrics, tracing)
  • mere krævende CI/CD-opsætning med mange pipelines

Hvis du ikke allerede har rimelig styr på deployment, monitorering og incident-håndtering, er det ofte bedre at investere dér først. Du kan fx starte med at bygge en enkel men solid pipeline (små CI-tiltag gør meget) og god logning, før du begynder at skære systemet i services.

Hvad er en modulær monolit – og hvorfor er den ofte den bedste mellemvej?

En modulær monolit er et samlet system, men med klare interne domænegrænser, så teamet kan udvikle og vedligeholde det mere disciplineret. For mange produkter er det den bedste mellemvej, fordi den giver struktur uden den driftkompleksitet, som følger med microservices.

En modulær monolit betyder typisk:

  • stadig én deployment, én applikation og ofte én database
  • men koden er opdelt i moduler/domæner med klare grænser
  • moduler taler sammen via veldefinerede interfaces, ikke “random” direkte kald ind i hinandens indre logik

Du kan tænke det som “microservices inde i én proces”:

  • domænelag: fx katalog, ordre, betaling, bruger
  • strenge regler for hvem der må kalde hvad
  • ingen direkte databaseadgang på tværs af moduler udenom deres interfaces

Fordele:

  • du beholder én simpel drift- og deploymodel
  • du træner teamet i klare domænegrænser og bedre arkitektur
  • du gør det lettere senere at flytte ét modul ud som selvstændig service, hvis behovet opstår

For mange danske teams er “modulær monolit som default” et sundt valg: du får orden i arkitekturen uden at skulle bygge Kubernetes, service mesh og avanceret observability fra dag ét.

Hvordan vælger du mellem monolit, modulær monolit og microservices?

Det bedste valg afhænger af, hvor komplekst produktet er, hvor modne teamets processer er, og hvor meget drift I kan absorbere. En simpel monolit er normalt bedst til en ny eller lille løsning, en modulær monolit er ofte bedst som mellemvej, og microservices bør først vælges, når der er et dokumenteret behov.

Du kan bruge denne enkle beslutningsmatrix som udgangspunkt. Giv hvert spørgsmål en score fra 1 til 5 og se, hvor du lander.

Kriterium 1-2 (lav) 3 (midt) 4-5 (høj)
Teamstørrelse & antal teams 1 – 8 devs, 1 team 8 – 15 devs, 1 – 2 teams 15+ devs, 2+ teams
Domænekompleksitet & klare grænser simpelt/uklart domæne begyndende domæner tydelige, relativt stabile domæner
Releasefrekvens & koordinationssmerte få releases, lav smerte jævne releases, lidt koordinering mange releases, høj koordinationssmerte
Drifts- og DevOps-modenhed basic scripts, begrænset monitorering CI/CD på vej, nogen logs/alarmer stabile pipelines, god observability, on-call
Skaleringsbehov & forskelle lav/moderat, jævnt fordelt nogle peaks i dele af systemet store peaks, meget forskellige skaleringsprofiler
Compliance & integrationskrav få krav og få integrationer nogle krav, flere integrationer tunge krav (fx GDPR, finans) og mange integrationer

Summér din score (maks 30):

  • 6 – 14 point: monolit er næsten altid bedst. Fokusér på ren kode og simple deployments.
  • 15 – 22 point: modulær monolit er ofte bedst. Byg klare interne domæner og gode grænser.
  • 23 – 30 point: microservices kan være relevante, hvis I også er klar organisatorisk og driftsmæssigt.

Måden du implementerer dit valg på er mindst lige så vigtig som selve valget:

  • Vælger du monolit: sørg for god struktur fra start, så du kan vokse uden kaos. Overvej fx at bruge erfaringer fra monorepo-arbejde og tydelig modulopdeling.
  • Vælger du modulær monolit: definer domænerne eksplicit og dokumentér afhængigheder. Det gør senere migration nemmere.
  • Vælger du microservices: planlæg også platform, CI/CD, logging og overvågning – ikke kun servicegrænser.

Hvad koster microservices i drift og kompleksitet?

Microservices er sjældent dyrere kun i cloudregningen; de er ofte dyrere i driftstid, platformopsætning, fejlfinding og koordinering. Den reelle omkostning er den samlede TCO, ikke bare antallet af servere eller containere.

Når du splitter i mange services, vokser især:

  • Platform engineering – du skal have styr på build, deploy og runtime for mange små enheder (ofte containere på en orkestreringsplatform).
  • CI/CD – flere repositories og pipelines, flere måder deploy kan fejle.
  • Observability – central logging, metrics og distributed tracing bliver nødvendige for at forstå, hvad der sker. Se fx hvorfor observability slår mavefornemmelse.
  • On-call & incidents – flere mulige fejlkilder, flere alarmer, mere tid på root cause-analyse.
  • Testmiljøer – det bliver sværere at have komplette og stabile testmiljøer, når der er mange services i spil.
  • Sikkerhed – flere netværksgrænser, flere tokens og secrets at håndtere forsvarligt (fx se om sikker håndtering af tokens).

Direkte infrastruktur-omkostninger (cloud, databaser, trafik) kan nogle gange blive lavere, fordi du skalerer mere målrettet. Men udvikler- og driftstiden stiger næsten altid, især i starten. Det er her, TCO (Total Cost of Ownership) reelt afgøres.

Hvis du overvejer microservices primært for “skalerbarhed”, er det værd også at se på muligheder som:

Hvad er en distributed monolith – og hvorfor er den et problem?

En distributed monolith er et system, der ser opdelt ud på papiret, men stadig er tæt koblet i praksis. Det giver både distribueret kompleksitet og monolitisk koordinationsbehov, altså de værste dele af begge verdener.

Typiske faresignaler på en distributed monolith:

  • Shared database – flere services skriver direkte til den samme database og tabeller.
  • Lange synkrone kæder – ét request krydser 5 – 10 services synkront, så et lille udfald ét sted lammer resten.
  • Fælles release-vindue – alle services skal deployes samtidigt, fordi de er gensidigt afhængige.
  • Høj koordinationssmerte – ethvert change kræver møder og koordinering på tværs af stort set alle teams.

Hvis du genkender det her, har du sandsynligvis ikke brug for flere microservices. Du har brug for:

  • klarere domæneopdeling og ejerskab
  • mindst én service ad gangen, der får sit eget, tydeligt dataansvar
  • at reducere synkrone afhængigheder og overveje, hvor event-baseret kommunikation giver mening

Distributed monolith er ofte resultatet af at splitte for tidligt eller uden klare arkitekturprincipper. Derfor er det bedre at starte med en velstruktureret, modulær monolit end med “pseudo-microservices”, der i praksis fungerer som én stor monolit over netværk.

Hvordan migrerer du fra monolit til microservices uden at bremse udviklingen?

Den sikreste vej er at starte med den eksisterende monolit, afgrænse et lille domæne, trække det ud gradvist og først gå videre, hvis den nye service faktisk reducerer koordinering eller skaleringsproblemer. Migration skal måles, ikke antages.

En realistisk migrationsmodel i 5 trin kunne se sådan ud:

  1. Kortlæg domæner og hotspots
    Identificér de vigtigste domæner i systemet (ordre, betaling, bruger osv.) og find hvor smerterne er størst: skaleringsproblemer, release-koordinering, hyppige konflikter i kodebasen.
  2. Forstærk den modulære monolit først
    Ryd op i den eksisterende kode, så domænerne er tydelige internt. Det giver dig en slags generalprøve på microservices, men stadig i én deployment.
  3. Vælg én kandidat-service
    Vælg et relativt afgrænset domæne med klar værdi ved opløsning. Undgå at starte med noget, der krydser alt (fx brugerhåndtering i hele systemet), med mindre det virkelig er nødvendigt.
  4. Etabler klare grænser
    Lav et veldefineret API og/eller events mellem monolitten og den nye service. Brug fx feature flags (gradvis udrulning med feature flags) til at skifte kald over i kontrollerede trin.
  5. Mål effekten og sæt stopkriterier
    Før du fortsætter, så mål: er koordinationssmerte faldet? Er skaleringsproblemet reduceret? Er driftens kompleksitet blevet uoverskuelig? Hvis gevinsten er lille eller negativ, er det et tegn på at bremse – måske skal resten forblive modulær monolit.

Undervejs er det afgørende, at du har:

  • solid teststrategi, så du kan flytte funktionalitet uden alt for meget risiko
  • gode database-migrationsprocesser, hvis data flyttes (database-migrationer i teams)
  • et minimum af observability, så du kan se, hvad der sker, når du skifter trafik over

En vigtig pointe: du har ikke “fejlet”, hvis du stopper migrationen halvvejs og lander på en modulær monolit med få strategiske services. Det kan sagtens være den økonomisk og teknisk mest fornuftige løsning.

Hvordan påvirker organisation, drift og compliance arkitekturvalget?

Arkitekturvalg handler ikke kun om teknologi, men om hvordan teamet arbejder, hvor moden driften er, og hvilke krav data og compliance stiller. I danske produktteams er den største risiko ofte at vælge en arkitektur, som organisationen endnu ikke kan drive sikkert.

Nogle vigtige organisatoriske faktorer:

  • Conway’s Law – systemet kommer ofte til at ligne organisationens kommunikationsstruktur. Har I ikke reelt autonome teams, er det svært at få reelt autonome services.
  • Serviceejerskab – ved alle, hvem der ejer hvilken del af systemet, og hvem der reagerer, når noget går ned?
  • Driftskapacitet – har I tid og kompetencer til at køre 10+ services i produktion med monitorering, backup og incident-håndtering? Se fx hvad god systemdrift for udviklere faktisk indebærer.

På compliance-siden (fx GDPR) handler det om:

  • hvem der ejer og har adgang til hvilke data
  • hvordan du kan dokumentere og logge adgange
  • hvordan du håndterer sletning og dataportabilitet

Det er ikke selve valget “monolit vs microservices”, der afgør om du er compliant, men:

  • om datamodellen er gennemtænkt
  • om du har styr på logging og adgangskontrol
  • om du kan forklare, hvor persondata flyder og hvorfor

For små teams med danske kunder er det ofte tryggere at holde arkitekturen simpel og i stedet investere tid i governance og sikkerhed, fx gennem gode praksisser for IT- og cybersikkerhed i teams.

Hvilke tegn viser, at monolitten bør opdeles nu?

Monolitten bør typisk først opdeles, når release-koordinering, team-blokeringer, meget forskellige skaleringsbehov eller vedvarende driftspres gør den nuværende struktur dyrere end en mere opdelt model.

Kig især efter disse tegn:

  • Release-flaskehalse – hver release tager meget lang tid at teste og kræver koordinering mellem flere teams.
  • Kodekonflikter og blokering – teams træder konstant hinanden over tæerne i samme mapper og moduler.
  • Onboarding er tung – nye udviklere skal forstå det meste af systemet for at levere simple ændringer.
  • Uens skaleringsbehov – enkelte funktioner presser ressourcerne, mens resten kører afslappet.
  • Driftspres – ét hjørne af systemet skaber mange incidents, men du er nødt til at deploye hele monolitten for at rette det.

Selv hvis du genkender flere af tegnene, er næste skridt sjældent “fuld microservices” i ét hug. Ofte vil rækkefølgen være:

  • ryd op og gør monolitten mere modulær
  • forbedr CI/CD og test, så du kan shippe oftere uden tårer
  • flyt enkelte, velvalgte domæner ud som services, hvis det giver tydelig gevinst

Det gør overgangsperioden langt mere kontrollerbar, og det giver dig data til at vurdere, om mere opsplitning er indsatsen værd.

Mål deploy-leadtime, build- og testtider, antal mergekonflikter og PR-ventetid, samt hvilke endpoints eller funktioner som står for størstedelen af CPU/latency/fejl. Undersøg også driftsindikatorer: skaleringshotspots (hvor kun en del af systemet er belastet), hyppige produktionsfejl med stor blast-radius, og tid brugt på release-koordinering. Når disse tal konsekvent bremser udvikling eller drift, har du et stærkt argument for at udskille services.
Definér klare domænegrænser efter princippet bounded context fra DDD og organiser kode som vertikale slices - hver modul skal eje sin forretningslogik og grænseflader. Håndhæv grænser med pakke-moduler, interfaces, adgangsrestriktioner og CI-regler (fx arkitekturtests), og undgå delt mutable global tilstand. Start med små, velafgrænsede moduler og refaktor løbende for at holde afhængighederne klare.
Brug orkestrering (f.eks. Kubernetes), en API-gateway, distribueret tracing (OpenTelemetry + Jaeger), centraliseret logging (ELK/Fluentd) og metrics (Prometheus/Grafana) for observability. Suppler med service-mesh (Linkerd/Istio) til trafikstyring, contract testing (Pact) for API-stabilitet og automatiserede CI/CD-pipelines med rollback-mekanismer. Disse værktøjer reducerer driftsbyrden, men kræver også kompetencer og opsætningstid.
Brug strangler-figuren: udpeg en enkelt vertikal funktionalitet, ekstraher den til en ny service og indsæt en adapter/anti-corruption layer, så gamle og nye systemer kan køre parallelt. Kør kontrakttests, deploy den nye service uafhængigt og skift gradvist trafik over, mens du beholder central overvågning og rollback-plan. Gør migrationen iterativ og målorienteret - stop når den næste udtræk ikke længere løser et konkret problem.

Sara Vestergaard er selvlært kode-nørd, der stille og roligt er gået fra at rode med en enkelt HTML-side til at bygge små værktøjer, scripts og hjemmesider til sig selv og vennerne. Hun startede med at lave en simpel band-hjemmeside som teenager og opdagede, hvor tilfredsstillende det er, når noget, du har skrevet, pludselig lever på skærmen.

For Sara handler kodning ikke om store ord eller imponerende titler, men om meget konkrete problemer: den kedelige opgave, der tager for lang tid, den ven der mangler en lille porteføljeside, eller den liste, der burde sortere sig selv. Hun elsker at pille ting fra hinanden – også kode – for at se, hvad der egentlig foregår, og hun har brugt utallige aftener på at google fejlbeskeder, teste små eksempler og langsomt bygge sin forståelse op.

På Coding Class deler hun den tilgang videre. Hun skriver til dig, der gerne vil lære at kode ved at gøre det i praksis: små projekter, korte kodebidder og forklaringer, der hænger sammen med det, du faktisk sidder med på skærmen. Hun skærer ind til benet, viser typiske fejl og deres løsninger og giver altid et forslag til, hvordan du kan bygge en tand videre, når grundideen først virker.

Når hun ikke skriver til Coding Class eller nørkler med nye små projekter, hænger Sara på klatrevæggen, vander sine altanplanter eller spiller gamle Nintendo-spil. Men hun ender næsten altid tilbage ved tasterne – for der er altid endnu en lille ting, der kunne være smartere, hurtigere eller bare lidt sjovere at bruge.

Send kommentar

You May Have Missed