Jakten på fem tusen skatteberegninger i sekundet

De store sky-leverandørene har utvidet tjenestespekteret sitt mye de siste par årene. Vi i BEKK ønsket å se om vi kunne lage en svært skalerbar løsning for skatteberegning på en av de allmenne skyplattformene, helt uten server-oppsett. Valget falt på AWS, og denne posten forteller om vårt forsøk på å snekre sammen en kraftig beregningsløsning ved hjelp av DynamoDB, Kinesis og Lambda.

Bekk Consulting
Bekk

--

Skrevet av Jørn Ola Birkeland

Skatteetaten er i ferd med å utvikle en ny plattform for forskudd- og skatteberegning, som skal erstatte dagens løsning på stormaskin. Målet er en arkitektur som er fleksibel, skalerbar, robust, og ikke minst fremtidsrettet. Løsningen er i produksjon, og videreutvikles fortløpende.

En beskrivelse av Skatteetatens strategi og innretning ligger her, og en overordnet arkitekturtilnærming ligger her.

I BEKK ønsket vi å teste om arkitekturen enkelt lot seg flytte over til en av de allmenne skyleverandørene, og om det er mulig å sette opp en skalerbar beregningsplattform kun ved hjelp av SaaS-tjenester i skyen. Vi mente det ville være en god indikator på om den nye arkitekturen når målet om å være fremtidsrettet.

Skattedomenet er komplekst, og med en ganske omfattende informasjonsmodell. Det er to hovedtyper informasjon Skatteetaten må vite om deg for å beregne skatten din. Det første er skattegrunnlaget, som inneholder verdiene av alt du eier, tjener, skylder og har av utgifter og fradrag. Det andre er skatteplikten, som er informsjon om deg som skattyter som kan påvirke skatteberegningen din, f.eks alder, bosted og familieforhold.

I den nye løsningen er skattegrunnlaget og skatteplikten reperesentert som XML-dokumenter i et sentralt dokumentlager. Stegene i din skatteberegning er da ganske enkle:

  1. Hent skattegrunnlaget ditt og skatteplikten din som XML fra dokumentlageret
  2. Kall skatteberegningsfunksjonen med dokumentene som input, og få returnert et XML-dokument med beregnete skatter og avgifter
  3. Skriv beregnet-skatt-dokumentet som XML tilbake til dokumentlageret

For å beregne skattene for alle skattyterne i Norge, kreves ikke annet enn at funksjonen kalles med de to dokumentene for alle i befolkningen. I teorien trengs ikke full skatteberegning å kjøres særlig ofte, men i praksis er det interessant å kjøre den mange ganger i forbindelse med testing og mange typer analyser og rapportering. Dermed er det kritisk at beregningen kan kjøres raskt.

Logikken i skatteberegningsfunksjonen er omfattende, men API’et er enkelt og har ingen andre avhengigheter. Det er et godt utgangspunkt for parallellisering og skalering. Imidlertid er en skalerbar arkitektur komplisert å bygge og drifte, og spesielt en hvor vi ønsker ekstremt høy ytelse i korte perioder, for så ikke å gjøre noen ting på en stund. Dette er utfordringer vi ville ventet at sky-plattformene var gode på.

Vi satte oss et passe hårete mål: Vi ønsket fem tusen skatteberegninger i sekundet. Det tilsvarer å beregne skatteoppgjøret for landets befolkning på under kvarteret, som vi vil si er et minimumsnivå for kunne kjøre et iterativt utviklingsløp.

Arkitekturtilpasningen vi så for oss i skyen, har tre hovedkomponenter:

  • Et datalager som vi kan putte skatteplikt- og skattegrunnlagsdokumenter i.
  • En beregningsfunksjon som tar imot ett eller flere fødselsnumre, leser de tilhørende dokumentene fra datalageret, gjør skatteberegningen, og skriver beregnet-skatt-dokumentet tilbake til datalageret.
  • En meldingstjeneste som vi kan benytte til å sende fødselsnumre til beregningfunksjonen.

Valget falt i denne omgang på Amazon Web Services (AWS), som regnes som markedsledende, men både Microsoft og Google har i utgangspunktet tjenester som tilsvarer det AWS kan tilby for den løsningen vi endte opp med å lage. De tre tjenestene vi til slutt bygde arkitekturen vår på, ble:

  • DynamoDB for datalager
  • Lambda for å kalle beregningsfunksjonen (som er den samme som kjører i produksjon i dag)
  • Kinesis som meldingstjeneste

Eksemplene og koden som vi beskriver, forutsetter at du har opprettet konto hos AWS, og gjort de nødvendige grepene for å opprette en sikker bruker. Alle AWS sine tjenester har API’er, som i en reell setting er mer effektive å bruke, men her vil vi utelukkende lene oss på web-konsollene til tjenestene. AWS har datasentre over hele verden, og i utgangspunktet kan bare tjenestene snakke med hverandre innenfor samme region. Vi valgte Europa, og nærmere bestemt senteret i Frankfurt.

MERK: Under alle testene benyttet vi oss kun av syntetiske data, men som tilsvarer informasjonen for en gjennomsnittlig skattyter. Der vi snakker om “fødselsnumre” er det kun snakk om identifikatorer opprettet for anledningen.

Oppsett av AWS-arkitekturen

DynamoDB

XML-dokumentene skal ligge i et datalager, og AWS tilbyr flere muligheter. S3 var en av de første AWS-tjenestene, og det er et enkelt nøkkel-verdi-lager. I dag brukes det ofte som et fil-lager, og det er et enkelt verktøy for å lage et nettsted med statiske sider. Ved første øyekast virker det en god match, siden vi kan lage en bøtte (bucket) for skattepliktsdokument og en bøtte for skattegrunnlag, og slå opp i hver av dem med fødselsnummer som nøkkel. Imidlertid er ikke S3 bygget for gruppehenting og -skriving (batch) av dokumenter, så det er litt tregt. Den andre ytterligheten er RDS, som tilbyr tradisjonelle relasjonsdatabase-motorer, som det selvfølgelig også er mulig å lagre XML-dokumenter i.

DynamoDB var et naturlig valg for oss. Det er et moderne skjemaløst lager, og støtter et fleksibelt antall attributter, i tillegg til både enkle og sammensatte primærnøkler, og det er mulig å lage indekser på attributtene for raske oppslag utenom primærnøkler. Det støtter også eksplisitte typer på attributtverdiene. Triggere er en annen nyttig funksjonalitet, som lar DynamoDB — via DynamoDB Streams — kalle en Lambda-funksjon hver gang det skjer en hendelse. Og ikke minst er det mulig å skrive og lese i grupper.

Første skritt var å laste opp skatteplikts- og skattegrunnlagsdokumenter til DynamoDB. Vi gikk for én million av hver i første omgang. Der var ingen grunn til å skille på innholdet — hele millionen fikk identiske versjoner av typiske (men syntetiske) dokumenter.

Vi opprettet tre tabeller i web-konsollet:

  • Skattegrunnlag
  • Skatteplikt
  • BeregnetSkatt

I tillegg til navnet, så må du oppgi en primærnøkkel. Vi valgte fnr (fødselsnummer) av typen string. Vi trengte ingen sorteringsnøkkel (sort key), og aksepterte ellers standardinnstillingene.

Vi lagde en liten applikasjon som leser de to dokumenttypene fra ressursfiler i pakken og sender dem til DynamoDB. Før appliksjonen kan kjøre, må det være mulig for AWS-klient-biblioteket å finne pålogginginformasjon. Det kan også gjøres på flere måter, og vi valgte å legge AWS-nøklene som to miljøvariabler, AWS_ACCESS_KEY og AWS_SECRET_KEY.

Applikasjonen vil kunne kjøre nå, men den møter raskt et problem. DynamoDB begrenser skrive- og leseoperasjoner til konfigurerte Write Capacity Units (WCU) og Read Capacity Units (RCU). Én RCU gir deg lesing av inntil 4 kB per sekund, mens én WCU lar deg skrive 1 kB per sekund. Skriver eller leser du hyppigere eller har større datamenger, så øker antall brukte RCU/WCU lineært. Du må konfigurere opp tilgjengelig RCU/WCU til tilstrekkelig høyt nivå til å håndtere belastningen, og det gjøres per tabell. DynamoDB godtar at man overskrider grensene i korte perioder, men det stopper fort opp med 2 millioner dokumenter.

MERK: Du betaler for konfigurert kapasitet, så den bør ikke være for høy. Du kan justere opp og ned, men ned kan du kun gjøre 4 ganger i døgnet.

Begge filene var på rundt 1 kB, skatteplikten litt under, og skattegrunnlaget litt over. Standard oppsett er 5 RCU og 5 WCU, og det var altfor lite. Litt eksperimentering viste at opplastingsapplikasjonen klarte en gjennomstrømning på mellom 1300 og 2000 dokumenter per sekund, og det viste seg å holde med 2000 WCU på skattegrunnlag- og skatteplikttabellene under opplastingen. Det tok 20 minutter å laste opp de to millonene dokumenter. Vi hadde ikke tenkt å gjøre det igjen, så vi gjorde ingen forsøk på å optimalisere det.

Kinesis

Det finnes flere tjenester som vi kunne ha brukte til å sende fødselsnumre til en beregningstjeneste. Simple Notification Service (SNS) og Simple Queue Service (SQS) er to eksempler, men vi endte med Kinesis.

Kinesis er ikke egentlig en meldingstjeneste, men AWS sin tjeneste for å håndtere sanntidsproessering av store strømmer av data. En datastrøm (stream) kan deles opp i mange delstrømmer (shards). Kinesis garanterer at rekkefølgen i en delstrøm blir bevart, men ikke at data på tvers av alle delstrømmer blir levert i samme rekkefølge som de ble skrevet. En klient kan polle strømmen, og hente et antall dataelementer fra hver delstrøm. Et dataelement opprettes med en partisjonsnøkkel (partition key), og elementer med samme partisjonsnøkkel er garantert å havne i samme delstrøm. Det er en del begrensninger på hvor ofte og hvor mye data som kan skrives til og leses fra en delstrøm per tidsenhet.

Kinesis kan være en hendelseskilde (event source) for andre tjenester, som Lambda. Tjenesten var spesielt attraktiv for oss fordi dokumentasjonen sier at Lambda vil starte like mange samtidige eksekveringer som det er delstrømmer i Kinesis-strømmen, og dermed hadde vi en tilsynelatende enkel skaleringsmekanisme gjennom å trigge en Lambda-funksjon fra Kinesis, og øke antall delstrømmer for å få den ytelsen vi ville ha. Lambda vil også rekjøre hendelser fra Kinesis inntil et døgn (kan økes til en uke) hvis noe feiler under kjøringen, for eksempel ved tidsavbrudd.

Det går raskt å opprette en Kinesis datastrøm i web-konsollet, og du trenger kun:

  • Navn — vi valgte FnrStream
  • Antall delstrømmer (shards) — maksimum i Frankfurt-regionen er 25.

MERK: Du betaler for antall delstrøm-timer (Shard hours), likegyldig om det lastes opp og leses data eller ikke.

Koden for å fylle Kinesis-strømmen FnrStream med én million fødselsnumre ligger her. Kinesis lar en gruppere dataelementer ved opplasting, men har en øvre begrensning på 100 elementer.

Lambda

Lambda eksekverer et stykke kode når det skjer en hendelse, og vi ville bruke en Lambda-funksjon til å kjøre beregningskoden. For tiden støtter Lambda tre språk/plattformer; Python, Node.js og Java 8. Vi valgte Java 8, og det å opprette en Lambda-funksjon i java med Maven er enkelt, og et eksempel på en enkel pom-fil er her.

I pakken trengs det en klasse med en metode som kan trigges ved en hendelse. Lambda støtter hendelser av mange typer, men vi skal trigge ved hjelp av Kinesis. Her er det som trengs for å bli kalt av Lambda når det skjer en Kinesis-hendelse:

package no.bekk.test.aws;

import com.amazonaws.services.lambda.runtime.events.KinesisEvent;

public class SkatteberegningKinesis {

public void kinesisRecordHandler(KinesisEvent event) {
System.out.println("Kinesis-hendelse mottatt. # dataelementer " + event.getRecords().size());
}
}

>mvn package i prosjekt-katalogen gir en jar som inneholder alle avhengigheter.

Etter at pakken er bygd, er det rett frem å lage Lambda-funksjonen, og følgende trengs for å opprette funskjonen i web-konsollet:

  • Navn — kan være hva som helst.
  • Kjøretidsmiljø (runtime) — her velger vi Java 8.
  • Kode — for forforholdsvis små pakker (anbefalt under 10 MB) kan du laste opp jar’en direkte. Ellers kan du gå omveien via S3.
  • Funksjon (handler) — metode som skal kalles, i vårt eksempel no.bekk.test.aws.SkatteberegningKinesis::kinesisRecordHandler.
  • Minne — vi valgte 512 MB (standard).
  • Tidsbegrensning (timeout) — hvor lenge funksjonen kan kjøre før den avbrytes. Maks er 3 minutter, og vi valgte 90 sekunder.
  • Rolle — med hvilke rettigheter Lambda-funksjonen kjører.

Rolle-biten krever litt mer forklaring. AWS har en egen tjeneste og konsoll for å administrere tilganger — IAM (Identity and Access Management). Ingenting skjer i AWS at uten at brukeren/rollen har rettigheter til det. Vår Lambda-funksjon skal kalles av Kinesis og trenger rettigheter til å lese fra og skrive til DynamoDB. Vi opprettet rollen lambda_kinesis_dynamodb_role, men den kan ikke gjøre noe før det blir knyttet regler (policy) til den. Våre regler gir rollen rett til å kalle en hvilken som helst Lambda-funksjon, lese fra en hvilken som helst Kinesis-strøm, opprette og skrive til logger, og alle tilganger til DynamoDB. Det er et ganske grovkornet regelsett, i et reelt kjøremiljø bør de være langt mer restriktive.

Når Lambda-funksjonen er opprettet, kan det knyttes til én eller flere hendelseskilder (event source), slik at funksjonen kjøres når noe skjer. Vi har valgt Kinesis, og da må følgende defineres:

  • Navnet på datastrømmen — her FnrStream
  • Gruppestørrelse (batch size) — angir maksimum antall dataelementer som kan leveres til Lambda-funksjonen i et kall. Våre dataelementer er fødselsnummre, så vi valgte 100, som er standard.

Kjøring av skatteberegning

Kjapt oppsumert hadde vi nå følgende:

  • Tre tabeller i DynamoDB — Skattegrunnlag og Skatteplikt, som hadde én million dokumenter hver, mens BeregnetSkatt var tom.
  • En Kinesis-strøm, FnrStream med 25 delstrømmer
  • En banal Lambda-funksjon som trigger på Kinesis-hendelser fra FnrStream, og skriver ut hvor mange dataelementer som er mottatt. Vi har bedt om at det skal sendes over maksimalt 100 dataelementer - her fødselsnumre - om gangen.

En kjøring med ti tusen fødselsnumre gav 25 logger i Lambda, som viste at Kinesis trigget den enkle Lambda-funksjonen vår.

Neste skritt var å skrive beregningskoden i Lambda-funksjonen. Da var vi tilbake ved utgangspunktet, der følgende måtte gjøres:

  • Hente og deserialisere skatteplikts- og skattegrunnlags-dokumentene for demottatte fødselsnumrene
  • Kjøre skatteberegningen for hver av dokumentparene og samle opp beregnet-skatt-dokumentene
  • Skriv beregnet-skatt-dokumentene til BeregnetSkatt-tabellen med fødselsnummer som nøkkel

Koden for håndtering av Kinesis-hendelser utvidet vi nå til å konvertere dataelementene til fødselsnumre, dele opp listen i passe biter (25 er maks elementer som kan skrives til DynamoDB i en operasjon) og sende fødselsnumre og DynamoDB-klient til selve skatteberegningenskoden. Den er på drøye 100 linjer, og dekker det som trengs av lesing fra og skriving til DynamoDB, serialisering og deserialisering av XML-dokumenter, og selve beregningen.

Første iterasjon

Før vi kjørte, måtte vi justere kapasiteten på DynamoDB. Beregnet-skatt-dokumentet er større enn de andre dokumentene, over 2,5 kB. Vi prøvde oss med følgende kapasitet på tabellene:

  • Skattegrunnlag: 2000 RCU, 1 WCU
  • Skatteplikt: 2000 RCU, 1 WCU
  • BeregnetSkatt: 1 RCU, 5000 WCU

Kinesis-strømmen FnrStream opprettet vi på nytt med 25 delstrømmer (husk at det koster penger å ha den liggende, så vi sletter hver gang), og så la vi den til som hendelseskilde på Lambda-funksjonen vår. Vi prøvde oss med hundre tusen fødselsnumre i første omgang. Den gode nyheten var at det virket, og vi fikk 25 samtidige eksekveringer, som vi håpet på. Den dårlige nyheten var at det ikke virket kjempebra.

Problem #1

Det å laste opp hundre tusen fødselsnumre i grupper av 100 til Kinesis, tok rundt 2 minuter og 15 sekunder. Det nærmer seg en halvtime med en million, og over to timer for hele landets befolkning. Det var ikke godt nok.

Løsningen på det var å sende opp flere fødselsnumre i hvert Kinesis-dataelement. Vi skrev om Kinesis-klienten til å komma-separere ca 100 fødselsnumre til et datelement, og sende dem i grupper av ca 100 til Kinesis, dvs ca ti tusen fødselsnumre per forespørsel. Den nye koden laster opp hundre tusen fødselsnumre på rundt to sekunder, og én milion på under 20 sekunder, som må sies å være en grei forbedring.

Koden i lambda-funksjonen måtte da skrives om til å håndtere det, og det krevde bare å legge til én linje kode.

Det hadde igjen konsekvenser for Lambda-funksjonen, som var konfigurert til å ta imot 100 dataelementer fra Kinesis i slengen. Det betydde nå ti tusen fødselsnumre, så vi justerte ned gruppestørrelsen (batch size) fra 100 til 1, slik at antall fødselsnumre sendt til funksjonen forble det samme.

Problem #2

Den andre utfordringer var at Lambda-funksjonen var treg. Her er et utsnitt av én av de 25 loggene:

Logg

Den viser at Lambda-funksjonen blir kalt med 100 fødselsnumre, som deles opp i 4 deler á 25 fødselsnummer, som behandles etter hverandre. Det er akkurat som ventet. Mer skuffende er at kjøring av funksjonen i snitt bruker 126 ms per fødselsnummer, altså snaue 8 i sekundet.

Selve skatteberegning av én skattyter på lokal maskin tar ca 10–15 ms. Kjøringen i Lambda tok både fire og fem ganger så lang tid, som loggen viser, og noen ganger over 100 ms. Dokumenthenting og -skriving var raskere enn lokalt, som forventet, men ren prosessering tok mye tid. Konsekvensen var at vi aldri var i nærheten av å treffe DynamoDB-grensene. Utsnittet under viser WCU-forbruket for BeregnetSkatt.

Logg

Sjarmen med Lambda, er at det er lite som må konfigureres. Men det er også lite som kan konfigureres, og selv om vi kunne kjøre på med logging for å finne ut hva som skjedde, så var det ikke sikkert at vi kunne gjøre noe med det. Svaret kom litt tilfeldig. Loggen viste at en lambda-kjøring bare brukte rundt 130 MB minne, og siden minne koster penger, så konfigurerte vi den ned fra 512 MB til 192 MB. Da ble prosessering enda tregere. Mistanken var da vekket — selv om loggen sa noe annet, så trengte vi kanskje mer minne likevel. Ganske riktig, ved å justere opp minnebruken til 1024 MB, så ble prosesseringsytelsen vesentlig forbedret, og tilnærmet det vi så lokalt.

Problem #3

Begrensningen på 25 delstrømmer (shards) i Frankfurt betydde at vi, selv om vi fikk fikset de andre tingene, neppe ville kunne klare mer enn 1500–2000 beregninger i sekundet. Vi sendte en henvendelse til AWS-support, og på under en time fikk tilgang til å opprette Kinesis-strømmer med inntil 100 delstrømmer.

Andre iterasjon

Vi opprettet Kinesis-strømmen FnrStream med 100 delstrømmer, og konfigurerte Lambda-funksjonen til å bruke den som hendelseskilde med gruppestørrelse 5. Vi regnet med greit å kunne håndtere ca 500 fødselsnumre i hver Lambda-eksekvering innen tidsfristen vår på 90 sekunder. Med større minne (1024 MB), så regnet vi også med høyere ytelse, og derfor økte vi DynamoDB-begrensningene igjen:

  • Skattegrunnlag: 3 000 RCU, 1 WCU
  • Skatteplikt: 3 000 RCU, 1 WCU
  • BeregnetSkatt: 1 RCU, 10 000 WCU

Vi slo til med én million fødselsnumre denne gangen, og resultatene var forsåvidt oppløftende. Som loggen viser, klarte hver Lambda-eksekvering å lese grunnlag, beregne skatt og skrive ned resultatet for over 60 fødselsnumre i sekundet.

Logg

Men det var fortsatt problemer.

Problem #4

Selv om Kinesis-strømmen hadde 100 delstrømmer, så ble det bare 50 samtidige eksekveringer. Mens antall delstrømmer under 50 så ut til å gi 1-til-1 med antall samtidige Lambda-eksekveringer, så ble alt over 50 begrenset til nøyaktig 50. Da vi sjekket Kinesis-strømmen etter å ha lastet opp én million fødselsnummer, dvs ti tusen dataelementer, så inneholdt alle delstrømmer data. Det så altså ut som partisjoneringen virket som forventet, og det var mer en nok data til at det ville være fordelaktig å kjøre opp flere eksekveringer. Vi har forsøkt med noen runder med AWS-support uten å finne en forklaring på hvorfor det skjer, og håper at det er en fiksbar begrensning et eller annet sted. Vår hypotese var tross alt at vi kunne skalere enkelt ved å øke antall delstrømmer i Kinesis-strømmen. Det er heldigvis mulig å komme seg rundt akkurat det problemet uten altfor mye arbeid, som vi skal se om et øyeblikk.

Problem #5

Logg

Skriving mot DynamoDB viste seg å være tett på 10 000 WCU, selv med bare 50 delstrømmer, og det er også i utgangspunktet øvre grense for hva du kan konfigurere opp i Frankfurt. Igjen var det bare å sende en henvendelse til AWS-support for å få økt grensen, denne gang til 30 000.

Tredje iterasjon

Delstrømsbegrensingen på 50 kunne vi omgå ved å opprette flere Kinesis-strømmer og dele fødselsnumrene på hver av dem. Lambda støtter å ha flere hendelsekilder knyttet til en og samme funksjon. Vi opprettet dermed to Kinesis-strømmer, FnrStream1 og FnrStream2, begge med 50 deltstrømmer. Disse knyttet vi til Lambda-funksjonen vår som hendelseskilder. Koden som sender fødselsnumre til Kinesis måtte da endres litt for å splitte fødselsnumrene på flere Kinesis-strømmer.

Igjen måtte vi øke DynamoDB-kapasiteten for å håndtere den forventede lasten:

  • Skattegrunnlag: 3 000 RCU, 1 WCU (uendret, brukte 1500 ved iterasjon 2)
  • Skatteplikt: 3 000 RCU, 1 WCU (uendret, brukte 1500 ved iterasjon 2)
  • BeregnetSkatt: 1 RCU, 30 000 WCU

Da denne ble kjørt, så fungerte endelig ting som håpet. Én million skatteberegninger, inkludert lesing fra og skriving til et datalager ble gjort unna på 2 minutter og 46 sekunder, eller rundt 6 000 skatteberegninger i sekundet i gjennomsnitt. Topp-ytelsen lå på rundt 8 000 beregninger i sekundet. Vi nådde 24 000 WCU på BeregnetSkatt-tabellene, mens de to andre tabellene vaket rundt 3000 RCU under kjøringen.

Vi hadde altså nådd vårt småhårete mål. Selv om det ser ut til foreløpig å være en begrensning på eksekveringer trigget av én Kinesis-strøm, er det forholdsvis enkelt å skalere ved å dele lasten på flere Kinesis-strømmer. Det beste er derfor at man kan gjøre ytterligere skalering fra dette nivået, så lenge DynamoDB-kapasiteten holder tritt.

Regningen, takk!

Kostnad for 1 mill skatteberegninger på ca 3 minutter følger under. Merk at det krever aktiv justering av DynamoDB-grenser og oppretting og sletting av Kinesis-strømmer rett før og etter kjøring.

Regningen

Den siste kjøringen kostet altså litt over halvannen amerikansk dollar, godt under 15 kroner etter dagens kurs. Legg merke til at dette er marginalkostnaden; for de fleste tjenestene er det gratis bruk til man når en terkselverdi, så de faktiske kostnadene ligger lavere innledningsvis.

Det er tydelig at skriving til DynamoDB er den store kostnadsdriveren, så det å konfigurere opp mye skrivekapasitet over langt tid, blir fort dyrt. Det samme gjelder for Kinesis-strømmer med med mange delstrømmer. Én time med det siste oppsettet ville ha kostet 26,5 $ (1,5 $ til Kinesis og 25 $ for DynamoDB), eller over 600 $ i døgnet. Det gjelder altså å være smart med kapasitetskonfigurasjonen sin.

Oppsummering

Testen vår viste det er enkelt å tilpasse skatteberegningsløsningen til en allmenn sky-plattform. Mengden kode som skulle til for å oppnå et skalerbart system i skyen, er svært lav — vi skrev til sammen under 500 linjer kode for å gjennomføre testene.

Mange av skytjenestene er helt nye og forbedres og utvides stadig. De har barnesykdommer, men er allerede nå på et godt nivå. Det legges ned store ressurser i å sikre høy oppetid og datavarighet. Om DynamoDb sier Amazon:

To achieve high uptime and durability, Amazon DynamoDB synchronously replicates data across three facilities within an AWS Region.

Slike ting er innbakt i prisen, og det er all grunn til å tro at tjenestetilbudet i fremtiden bare blir enda bedre. Og sammenliknet med prisen for å sette opp og forvalte et tilsvarende kjøretidsmiljø på egne servere, så ser kostnadsbildet for å betale kun for faktisk bruk i slike scenarier som vi har sett på her, svært mye gunstigere ut.

En annen sentral utfordring, er sikkerhet. I neste bloggpost skal vil se på nettopp det — hvordan bygger vi om denne løsningen slik at den blir sikker nok til å være et reelt altenativ.

I mellomtiden bør en sentral arkitekturjobb for løsninger som utvikles i dag, være å sørge for at de er tilpasset en fremtid der de kan kjøre i skyen, slik som Skatteetaten har klart. Det er mye som tyder på at de vil havne der før eller siden.

--

--