Från 60 repos till 1: så förenklade vi utvecklingen med ett Monorepo på lynes

Tech

Vi flyttade från 60+ repos till ett monorepo. Resultatet: färre buggar, snabbare utveckling, enklare kodgranskning och en tydlig struktur som gör teamet både effektivare och gladare.

Från 60 repos till 1: så förenklade vi utvecklingen med ett Monorepo på lynes
Från 60 repos till 1: så förenklade vi utvecklingen med ett Monorepo på lynes

lynes bygger vi kommunikations- och produktivitetsverktyg med en modern stack: Node.js + TypeScript på backend och TypeScript på frontend. Som många team började vi smått — ett par tjänster, några delade utilities och ett fåtal utvecklare. Men med tiden växte det.

Innan vi visste ordet av hade vi:

  • 60+ separata Git-repositories
  • 20+ delade moduler (publicerade till privat npm)
  • En växande röra av versionskonflikter, dubbelarbete och trasiga kontrakt mellan tjänster

Så vi gjorde en stor förändring. Vi flyttade allt till ett monorepo.

Och det har varit en riktig game-changer.

Varför vårt gamla upplägg höll oss tillbaka

När varje tjänst hade sitt eget repo och delade moduler publicerades separat gick utvecklingen långsamt — väldigt långsamt. Några av problemen vi stötte på:

  • Versionskonflikter överallt: En tjänst körde v1.2.0 av en delad modul, en annan körde v1.2.3. Något gick sönder, och vi fastnade i felsökning av spökbuggar.
  • Jobbigt att publicera: Att fixa en bugg i en delad modul innebar att höja versionen, publicera till npm, uppdatera beroenden i varje repo och testa manuellt. Massor av overhead.
  • Utvecklare undvek delad kod: Eftersom processen var både tidskrävande och riskfylld drog sig utvecklare ofta för att röra delad kod — även när de visste att något var fel.
  • Splittrat arbete: Att lägga till en ny funktion som påverkade flera tjänster innebar ofta 5–10 pull requests i olika repos. Att koordinera och granska dem var ett rent mardrömsscenario.

Övergången till Monorepo (utan fancypants-verktyg)

Vi använde inte något som Nx eller Turborepo. I stället:

  • Skapade vi ett enda GitHub-repo
  • Migrerade tjänster till undermappar (en i taget, under ca 6 månader)
  • Skrev egna skript för linting, tester och CI-workflows

Den svåraste delen? Att få symlinks att fungera smidigt i TypeScript, Jest, lint och Docker. Varje verktyg hade sina egna egenheter med symlinkade filer — från modulupplösningsproblem till felaktiga sökvägar. Men när vi väl knäckte det pusslet, föll allt annat på plats.

Så här fungerar det idag

Varje tjänst ligger i en mapp inne i monorepot.

Vi har mappar som:

/services/service-a
/services/service-b
/sharedModules
/sharedTypes

Under utveckling refererar tjänster till delade moduler och typer via symlinks.

Under CI eller Docker-build gör våra skript följande:

  • Ersätter symlinks genom att kopiera de faktiska filerna till Docker-build-kontexten
  • Använder Git-historik för att upptäcka vilka delade moduler som ändrats
  • Skannar källfiler för att se vilka tjänster som använder dem
  • Kör unittester endast på de tjänster som påverkas

Det här ger oss flexibiliteten med symlinks lokalt och stabiliteten med faktiska filkopior i builds.

En typ för att härska över alla

Typesäkerhet är en enorm vinst för oss. Vi använder samma TypeScript-typer i både backend och frontend.

De lagras i en delad mapp, symlinkas under utveckling, och kopieras till varje tjänst vid build. Så när en typ ändras:

  • Kommer varje tjänst och frontend som använder den direkt att krascha om något inte stämmer
  • Utvecklaren får omedelbar feedback innan merge

Det eliminerar helt de subtila buggarna där ett tjänstsvar ändrats men frontend fortfarande antog den gamla strukturen.

Pull requests som faktiskt är begripliga

Det här är enormt: Vi kan nu göra en pull request per feature.

Tidigare kunde en ny feature som påverkade flera tjänster kräva 10+ pull requests i 10 olika repos. Att granska dem i rätt ordning, synka godkännanden och se till att allt fungerade tillsammans var utmattande.

Nu:

  • Alla relaterade ändringar hamnar i en PR
  • Granskare kan se hela bilden
  • Testning blir mycket enklare

Det har förbättrat kodgranskningar dramatiskt och minskat antalet buggar som smyger sig igenom.

Delad linting, testning och regler

En annan underskattad vinst: vi har nu en enhetlig linting- och testkonfiguration.

Alla tjänster följer samma ESLint-regler, TypeScript-konfig och Jest-setup. Det håller vår kodbas konsekvent och sparar massor av tid vid uppstart av nya tjänster eller utvecklare.

Ingen mer gissning om vilket service som använder vilka regler eller vilken config-fil man måste uppdatera.

Vinsten

Här är vad vi har tjänat på flytten:

✅ Färre buggar

✅ Delad kod används faktiskt och underhålls

✅ Typändringar bryter tidigt och synligt — inte i produktion

✅ Snabbare utveckling och testning

✅ Enklare kodgranskningar

✅ Gladare utvecklare

Vi mäter inte hårda metrics som buggrapporter eller cykeltid, men för alla i teamet är det uppenbart att vi rör oss snabbare med mindre huvudvärk.

Vad vi skulle göra annorlunda

Ärligt talat? Vi skulle välja monorepo från början.

När vi startade hade vi bara 2–3 tjänster och ingen TypeScript, så multi-repo-modellen var logisk. Men så snart saker växte och delad logik ökade, vägde smärtan med splittrade repos snabbt tyngre än fördelarna.

Om du startar ett projekt nu, och du ens tror att du kommer dela kod mellan tjänster, spara dig besväret — börja med ett monorepo.

Avslutande tankar: bör du övergå till Monorepo?

Om du:

  • Har delad logik eller typer mellan tjänster
  • Använder TypeScript
  • Vill ha konsekvent verktygsstöd
  • Är trött på att hantera 20+ repos

…då ja, vi rekommenderar det varmt.

Och du behöver inte fancy verktyg eller ett stort team. Med några skräddarsydda skript och en tydlig struktur kan du få 90% av värdet utan extra komplexitet.

Har du frågor eller vill veta mer om vårt setup på Lynes? Hör gärna av dig — vi delar alltid gärna idéer!

Skriven av

David Erenger

David är en vass kodare som älskar långdistanslöpning, fokus och uthållighet präglar allt han gör.

Kontakta oss

Växel, Contact Center eller AI? Lynes är allt det – och lite till.

Lynes är mer än en vanlig företagsväxel – det är en komplett plattform för kundkommunikation och insikter. Jobba smartare med AI-agenter, automatiserade flöden och allt samlat i en enda app.

Ett urval av våra kunder

Svensk fastisghetsförmedling logoSvensk fastisghetsförmedling logo
Renta logo Renta logo
SwedolSwedol
FastighetsbyrånFastighetsbyrån
Linköping UniversitetLinköping Universitet
GeberitGeberit
Skåne MejerierSkåne Mejerier
No items found.
No items found.
No items found.

Intresserad? Prata med oss idag.

Formuläret visas endast på livesidan

Formuläret visas endast på livesidan