Lendo berättar om sin nya techstack och utmaningarna under resans gång

Lendo har nyligen bytt ut större delen av sin techstack för att vara rustade för uppskalning och för att smidigt och snabbt kunna hantera högtransaktionella dataöverföringar. Detta fångade Demandos intresse så vi tog kontakt för att se hur de löst deras tidigare utmaningar. Vi får också en inblick i arkitekturen och hur deras nya techstack är uppbyggd.

Ni har nyligen bytt ut stora delar av er tidigare techstack. Kan du berätta om vilka tekniker ni använde då och hur arkitekturen såg ut?

Vi hade en LAMP-stack som skalats upp till en lastbalanserare (nginx), två webb-servrar (Linux + PHP) och tre databas-servrar (MySQL i ett galerakluster).

Systemet var byggt i PHP med Zend Framework 1.

Vilka stora utmaningar hade ni med er tidigare lösning?

Plattformen hade funnits i mer än sex år och, på grund av flera orsaker, utvecklats till en monolit med flera interna beroenden och oklart strukturellt ansvar mellan de olika beståndsdelarna. Det var svårt att ändra något utan att något annat slutade fungera.

På grund av att den var byggd i ett synkront språk var det problem med att snabba upp processen. Det var onödiga ledtider som gjorde att kunder inte kunde se sina bud på en gång.

Innan bytet var det mer vanligt att vi sjösatte "quick fixes" för att släcka bränder som konstant uppstod. Effekten av att arbeta med kortsiktiga lösningar gjorde dock att kodbasen tillslut gjordes ohanterlig vilket resulterade i en monolit med interna beroende överallt.   

Berätta om er nya arkitektur och varför ni valt vissa tekniker?

Vår nuvarande techstack är byggd med cirka 60 tjänster, där de flesta är skrivna i Go. Dessa är uppdelade efter bästa förmåga och de områden vår verksamhet organisatoriskt är uppdelad i, vilket i domändriven design brukar refereras till som bounded context. Arkitekturen bygger på asynkrona meddelanden, som vi låter RabbitMQ hantera. Dessa meddelanden produceras och konsumeras av tjänsterna.

Vi använder en rad olika databaser, där varje tjänst använder en eller flera databaser efter de behov som finns, men majoriteten av använder PostgreSQL. Varje tjänst är uppbyggd med domändriven design där vi beskriver koden på ett sätt som är nära vår affärsverksamhet.

Vi använder Travis för att bygga, köra tester och producera färdiga containrar som sedan körs i Kubernetes, som sköter orkestreringen av dem.

Kan ni berätta hur de olika komponenterna i arkitekturen kommunicerar med varandra och hur ert flöde ser ut?

En användare interagerar med systemet genom en frontend uppbyggd i React. Alla requests som görs via frontend går genom ett API specifikt uppbyggt för den frontendapplikation som används. API:et har som uppgift att kontakta de interna tjänster som krävs för att utföra den önskade operationen. De tjänster som är berörda utför operationen, exempelvis att spara en ansökan, och svarar med resultatet tillbaka till användaren. Samtidigt skapar tjänsten även events via RabbitMQ om vad som hänt. RabbitMQ låter andra tjänster, som är intresserade, att lyssna på eventet och utföra det arbete som krävs. Detta låter användaren fortsätta i flödet, trots att systemet fortsätter exempelvis samla sekundär information i bakgrunden. Även dessa tjänster kan i sin tur skapa event som triggar ytterligare funktioner i systemet.

Beskriv den största utmaningen med att byta den gamla lösningen till den ni har idag och hur ni löste det?

Vår största utmaning låg i att produktionssätta den nya plattformen. Vi hade två alternativ i vårt val av att bygga den nya plattformen:

  1. Ett innebar att vi skulle bryta ut den gamla plattformen tjänst för tjänst.
  2. Det andra alternativet (som vi valde) var att bygga helt nytt och ersätta den gamla plattformen.

Vi delade upp trafiken i kundsegment, och gick i produktion med den nya plattformen med ett kundsegment i taget. När vi kände oss säkra på att den nya plattformen skulle hålla så valde vi att flytta över all trafik. Detta innebar att vi fick köra båda systemen parallellt under en övergångsperiod för att kunder skulle kunna slutföra sina låneprocesser i den gamla plattformen.

Finns det något verktyg eller teknik i er nuvarande techstack som ni är extra nöjda med? Berätta gärna varför.

Vi är väldigt nöjda med valet av Go för våra tjänster i backend. Vi började med att bygga dem i både PHP och Node.js, men märkte snabbt negativa effekter av dels stora images men även minnesanvändningen och avsaknaden av stöd för concurrency. En del av våra utvecklare hade använt Go för sina fritidsprojekt och vi gjorde tester där vi skrev om ett par services till Go och la mycket tid på arkitektur med domändriven design och lyckades få ner storlekarna på våra images och minnesanvändningen gick ner till en tiondel. Eftersom vi la mycket tid initialt på arkitekturen av våra services, främst på att modellera dem efter vår affärsdomän, så medförde det att produktiviteten hos utvecklarna har varit hög under hela projektet.

Valet av Kubernetes för att sammanföra alla enskilda tjänster och inte själva behöva hantera allt som rör lastbalansering och kontroll av enskilda beståndsdelars hälsa, tillgänglighet och uppgradering, har kunnat flytta fokus mer mot utveckling istället för att alla utvecklare även måste förstå hur tjänsterna sinsemellan kommunicerar och i vilken plattform de körs.

Har ni gjort några tekniska val/beslut under er resa som har fått negativa konsekvenser i efterhand? Hur gjorde ni i sådana fall för att lösa det?

När vi startade projektet med nya plattformen gjorde vi det vanliga misstaget att göra delar av den för tekniskt komplicerade. Vi ville ha en testbar plattform där vi kunde debugga kunders ansökningar och spela tillbaka dem till vissa exakta tidpunkter för att se vad som hade gått fel. Därför valde vi event sourcing. Vi valde Elasticsearch för att spara snapshots av våra ansökningar och på vissa ställen även Cassandra som databas för att spara data i kronologisk ordning.

Detta visade sig under projektets gång orsaka hög komplexitet och andra tekniska utmaningar där vi spenderade väldigt mycket tid på dessa tekniska implementationer utan att egentligen ta oss framåt i projektet.

Problemen nådde en kritisk punkt där vi var tvungna att utvärdera våra tekniska val — gå tillbaka till ritbordet och tänka igenom vilka problem vi faktiskt försöker lösa.

Vi la mycket tid på att undersöka dessa tekniker på djupet och förstå vad de faktiskt var bra på. Vi insåg att vi använt dem fel för de problem vi faktiskt har på Lendo, och valde därmed att göra oss av med event sourcing helt. Eftersom vi inte behövde snapshots längre försvann även Elasticsearch och ytterligare djupdykning i Cassandra insåg vi att PostgreSQL skulle passa oss bättre.

Vad har ni i er pipeline just nu?

Vi har stött på en del problem med växande datamängder sedan release, så där arbetar vi med att lösa prestandaproblem kopplade till dessa. Ett exempel på detta är att vi i flera delar av systemet gör sökningar med parametrar som ligger i olika tjänster. Vi har en separat sökmotor som indexerar data som är relevant för sökningarna men ju större mängd data vi har, desto längre tid tar våra sökningar. Det är inte hållbart i ett längre perspektiv, så här arbetar vi för fullt med att finna en lösning som är mest optimal för oss.

Lendo expanderar just nu och de kommande åren har vi siktet inställt på expansion till flera nya marknader. En stor utmaning i detta är att kunna återanvända tjänster även om marknader och produkter kan se väldigt annorlunda ut.

Hur ser ni på ert sätt att jobba?

Det här varierar beroende på vad som behöver göras. Vi har teams på 5-9 personer. Inom dessa kan vi har 2-3 personer som jobbar med en viss funktionalitet beroende på vad som behöver göras. Utvecklarna kan byta team om de vill göra det.

Hur ser era rekryteringsbehov ut framöver? Vad söker ni för kompetenser?

Vi söker nya kollegor som vill arbeta med frontend och kollegor som vill arbeta med backend. Vi letar alltid efter nya kollegor som är lagspelare, problemlösare och som hela tiden vill lära sig nya saker samt utvecklas. För att kunna veta vad som sker i en plattform som denna ställer det större krav på monitorering av mätpunkter och prestanda, därför har vi börjat bygga upp en site reliability-organisation (SRE) som har som ansvar att möjliggöra det och se till att detta är en del i utvecklingsarbetet.

Har du idéer på ett intressant eller roligt ämne att skriva om eller kanske till och med en redan färdig artikel? Klicka här för att läsa mer.

Demando Demando