/yrke/[yrke] 9 sektioner Svaret i hero: median, medel, p10, p90, sparkline. Sedan lönefördelning (DistributionBar), löneutveckling vs riket, per sektor, per kön, per region (NUTS 2), närliggande yrken, FAQ. Lutar på SCB AM0110 och YREG58.
All data på yrkesatlas.se kommer från 5 officiella svenska källor – SCB, SKR, Skatteverket, Arbetsförmedlingen och Konsumentverket. Varje datapunkt har en spårbar rad till en specifik tabell, ett publiceringsdatum och vår hämtningstidpunkt. Råfilerna är versionerade – vi skriver aldrig över.
Det mesta på den här sidan är operationaliseringen av dessa tre. Om något i resten av metodiken känns som att den motsäger ett av löftena – säg till, det är då en bugg.
Varje hämtning sparas som en tidsstämplad JSON-fil i data/raw/. Vi skriver aldrig över. SCB:s API kan gå ner, deras format kan ändras – databasen kan alltid byggas om från råfilerna deterministiskt.
data/raw/scb/AM0110_LonYrkeOSekN1_2026-05-20T08-14-22Z.json Bottom-up: tabellen ingest_log loggar varje körning med endpoint, rad-antal och råfil-path. Top-down: varje siffra på sajten visas under en <SourceNote> med SCB-tabellkod, publiceringsdatum och vår hämtningstidpunkt. Klicka på källan – du landar i tabellpaketet hos SCB.
Källa: SCB Lönestrukturstatistik · AM0110 · Publicerad 2025-06-15 · Hämtad 2026-05-20 När vi måste estimera – typiskt för kommunlöner, eftersom SCB inte publicerar lönedata på kommunnivå – säger vi det rakt ut, visar metoden, och redovisar osäkerheten. Aldrig en uppskattning utan etikett.
Kommunsidor: obligatorisk Callout om NUTS 2-modelleringen i hero Nio källtabeller från fem myndigheter. Inga proprietära källor, inga betalmurar, ingen ompaketerad data från tredjepartsleverantörer – alla siffror kan verifieras direkt hos källan.
När en sida visar data från flera källor (nettolön = SCB OE0101 +
Skatteverket-formeln) är båda namngivna i <SourceNote>
under blocket. Aldrig en sammanblandning utan ursprung.
| Tabell | Källa · vad vi hämtar | Frekvens | Driver |
|---|---|---|---|
| AM0110 | SCB Lönestrukturstatistik Median, medellön, p10, p90 per yrke × sektor × kön Årligen, juni · Yrkessidor, lönefördelning, lönejämförare | Årligen, juni | Yrkessidor, lönefördelning, lönejämförare |
| AM0110 (regional) | SCB Lön per region Medellön per NUTS 2-storregion × sektor × kön Årligen, juni · Region- och kommunsidor | Årligen, juni | Region- och kommunsidor |
| YREG58 | SCB Yrkesregistret Antal anställda per yrke (SSYK-3) × region × kön Årligen, mars · Kommunsidor, Location Quotient | Årligen, mars | Kommunsidor, Location Quotient |
| BE0101 | SCB Befolkningsstatistik Folkmängd per kommun, kön och ålder Kvartalsvis · Kommunsidor | Kvartalsvis | Kommunsidor |
| OE0101 | SCB / SKR Kommunalskatt Skatt till kommun, region och total per region × år Årligen, december (förskott) · Nettolön, kommunsidor, köpkraft | Årligen, december (förskott) | Nettolön, kommunsidor, köpkraft |
| PR0101 | SCB Konsumentprisindex KPI fastställda årsmedeltal (1980 = 100) Månadsvis · Inflation vs lön, reallönediagram | Månadsvis | Inflation vs lön, reallönediagram |
| – | Skatteverket Grundavdrag, jobbskatteavdrag, statlig brytpunkt Årligen, december · Nettolön, brytpunkt, konsult vs anställd | Årligen, december | Nettolön, brytpunkt, konsult vs anställd |
| – | Konsumentverket Standardbudget för 12 hushållstyper Årligen · Köpkraftskalkylator | Årligen | Köpkraftskalkylator |
| – | Arbetsförmedlingen Yrkesprognoser, bristyrken på 1- och 5-års sikt Halvårsvis · Yrkessidor (framtidsutsikter) | Halvårsvis | Yrkessidor (framtidsutsikter) |
Sex steg, varav två är "minne" (råfiler och git) och fyra är "transform" som alltid kan köras om från scratch. Om något går fel i steg 2–6 påverkar det inte stegen före – råfilen ligger kvar.
Den viktigaste designprincipen är separationen mellan minne och derivat. Råfilen är minne – den får aldrig röras. Databasen är derivat – den kan kastas och byggas om. Det gör att ett buggfix i normaliseringslogiken inte är farligt; vi kör bara om pipelinen mot samma råfiler och får en konsistent ny databas.
scb.ts-klienten hämtar tabellpaket och sparar svaret som råfil med ISO-tidsstämpel i namnet. Idempotent: samma anrop, samma filstruktur.
data/raw/<källa>/<tabell>_<typ>_<timestamp>.json Pivotera celler ur json-stat-strukturen till tabellrader. Strippa SCB:s prefix från valueTexts. Filtrera bort aggregatvärden som '0000 Samtliga yrken' när de inte ska in i faktatabellen.
Iterable av platta rader (yrke, år, sektor, kön, värde) En transaktion per körning. Alla fakta-tabeller är append-only – ny rad, inte UPDATE. revision-kolumnen är del av PK så SCB-revideringar av äldre år kan saminlagras utan att skriva över historiken.
site.db (~1,9M rader över fakta-tabellerna) Förberäknade vyer (metric_*) byggs om från rådata. Ingen state – kan alltid återskapas. Här ligger reallöner (KPI-deflaterade), CAGR, Location Quotient och regionala viktade SSYK-3-medellöner.
metric_* (kan repliceras från rådata) Sanity-checks: täckning per dimension (alla 290 kommuner? alla 589 yrken?), FK-konsistens, KPI-värden inom rimligt intervall. Build går inte vidare vid fel – siffrorna ska aldrig komma upp på sajten korrupta.
Pass / fail · loggad i ingest_log Statisk HTML genereras vid build-tid. Inga tunga beräkningar i runtime – sajten levereras från CDN. Vid SCB-release: ny ingest → ny build → ny deploy.
~2 700 statiska sidor till CDN SCB reviderar äldre års siffror regelbundet. Vår databas är därför temporal, inte mutation-baserad. Ny data blir en ny rad – aldrig en UPDATE.
Alla fakta-tabeller har år som dimension och en
revision-kolumn som del av primary key. Det betyder att en
revidering av t.ex. 2023 års siffror som publiceras senare än det
ursprungliga tabellpaketet kan tas in utan att förstöra den version vi
hade vid första hämtningen.
UI visar alltid senaste publicerade revision, men historiken finns kvar – både i råfilerna och i databasen. Det gör två saker möjliga: vi kan svara på "vilken siffra publicerades när?", och vi kan rendera löneutveckling över tid som riktig seriedata, inte som en aktuell ögonblicksbild på flera år.
Att kunna visa löneutveckling över tid är en explicit produktprincip – inte teknisk hygien. Historik är innehåll, inte arkiv.
data/raw/ behåller alltid originalvärdet så att en specifik
revision kan jämföras mot den ursprungliga publiceringen.
Fyra sidtyper, samma underliggande datalager. Varje sida börjar med svaret i första meningen – sedan kommer vinklarna.
/yrke/[yrke] 9 sektioner Svaret i hero: median, medel, p10, p90, sparkline. Sedan lönefördelning (DistributionBar), löneutveckling vs riket, per sektor, per kön, per region (NUTS 2), närliggande yrken, FAQ. Lutar på SCB AM0110 och YREG58.
/kommun/[kommun] 11 sektioner Obligatorisk NUTS 2-callout i hero – kommunlön är regionlön. Snabbtolkning (regelbaserad, inte AI). Topp-yrken med trend. Specialisering (LQ). Vad blir kvar efter skatt. Befolkning och skattutveckling över tid.
/region/[region] 5 sektioner En per NUTS 2-storregion. Äger lönedatan som vi tidigare doublade på alla 290 kommunsidor. Löneutveckling vs riket. Kommuner per län, länkat – inte duplicerat. Korta, tunga sidor.
/verktyg/* 5 sektioner Räknesnurror som körs lokalt i webbläsaren. Inga inmatade belopp lämnar din enhet, vi loggar inte din lön. Samma SCB- och Skatteverket-formler som datasidorna – öppen källkod på GitHub.
Tre typer av luckor i offentlig statistik. Vår regel: visa metoden, visa felmarginalen, märk datapunkten visuellt – eller säg att vi inte vet.
SCB publicerar inte lönedata på kommunnivå –
AM0110 LonYrkeRegion* går bara ner till NUTS 2 (åtta
storregioner + Riket). Vi visar därför regionens lön på
kommunsidor med en obligatorisk Callout högst upp som flaggar det.
Stockholms stad får Stockholms läns lön; Mölndal får
Västsveriges lön. Aldrig en låtsas-kommunmedian.
För kombinationer med få observationer (t.ex. ett specifikt yrke ×
kön × sektor) döljer SCB antalet helt – för att skydda individers
integritet. När vi räknar andelar i query-lagret sätter vi då
andel = null istället för att räkna 100 % på den ena
synliga raden. Site-koden respekterar null och
renderar inte falska procenttal.
Reallöner kräver KPI-deflatering. Regionala SSYK-3-medellöner i kommunens topp-yrken-tabell härleds genom att vikta SSYK-4-lönerna inom respektive grupp. Varje modellering har en metodik-rad i den specifika datavisualiseringen – du ska aldrig behöva läsa den här sidan för att förstå hur en siffra räknats fram.
Allt AI-genererat innehåll går genom en tre-stegs-pipeline: generera → validera → kritisera. Språkmodellen (LLM) får aldrig en öppen fråga, bara strukturerad data att rephrase:a.
Strict Zod-schema + OpenAI structured output. Språkmodellen får aldrig en öppen fråga, bara strukturerad input att rephrase:a. Prompten förbjuder företagsnamn, "drivs av"-fraser, superlativ och spekulation.
Syntaktisk kontroll. Alla siffror i texten måste finnas i inputdatan. Alla kapitaliserade ord måste finnas i en allowlist. En blacklist fångar spekulativa fraser ("tech-hub", "Sveriges bästa"). Failure → regenerera med feedback.
En andra AI-runda som faktagranskar texten mot inputdatan. Listar konkreta saklighetsfel: sektor som motsäger data, namngivna institutioner, numeriska påståenden utanför datan. Failure → manuell review eller regenerering.
Drafts committas i git som canonical output – texter vi har granskat
och accepterat. Vid varje AI-anrop sparas hela request + response
som råfil i data/raw/llm/, samma audit-princip som
SCB-rådata. Du kan se exakt vilken modell + vilket prompt som
producerade en given text.
Var språkmodellen används: intromeningar på yrkessidor som rephrase:ar strukturerad data till naturlig text. Var den inte används: sifferpåståenden, kausala slutsatser, jämförelser mellan källor, beslut om vad som är publiceringsvärt. Den biten gör vi själva.
Det vi låter bli är lika viktigt som det vi gör. Hela vitsen med en datadriven sajt är att den ska kunna citeras – och det går bara om vi undviker mönstren nedan.
"Det är en spännande utveckling att se hur löner förändras över tid." Ingen siffra, ingen insikt, ingen anledning att finnas på sajten.
Säg vad det beror på, inte att det beror på. Om vi inte vet – säg att vi inte vet, och varför datan inte räcker.
En modellerad siffra som ser ut som en mätning är värre än ingen siffra alls. Vi visar metoden, inte bara talet.
En FAQ ska besvara en fråga som faktiskt ställs om just det här yrket eller den här kommunen – inte fyllnadstext som återanvänds över hundra sidor. Hellre ingen FAQ alls än samma fyra frågor överallt.
Verktygen körs lokalt. Vi loggar inte lön, inte kommun, inte personnummer. Det går inte att läcka data vi aldrig samlat in.
"Forskning visar att…" är en röd flagga. Om en studie är värd att citera är den värd en URL och ett publiceringsdatum.
Frågar någon "var kom den här siffran ifrån?" ska svaret finnas på minst ett av lagren nedan. Tillsammans täcker de allt från råsvaret från SCB:s API till mänskligt skrivna noter när vi ändrat metodik.
| Lager | Vad det fångar | Behålls |
|---|---|---|
| Råfil data/raw/<källa>/ | Exakt API-svar från källan, ord för ord Alltid · aldrig överskrivet | Alltid · aldrig överskrivet |
| ingest_log site.db · ingest_log-tabell | En rad per körning: källa, endpoint, råfil-path, rad-antal, status Alltid | Alltid |
| Git Versionskontroll | Kod, schema-migrations, AI-drafts, SQL-recept för metrics Alltid · varje ändring är ett separat commit | Alltid · varje ändring är ett separat commit |
| Ändringslogg /andringslogg | Mänskligt skrivna noter när data eller metodik ändras Alltid · synlig för läsare | Alltid · synlig för läsare |
Hela poängen med spårbar metodik är att fel kan hittas – av oss eller av dig. Om en siffra ser konstig ut, om en källa har uppdaterats utan att vi fångat det, eller om något i metodiken inte håller – hör av dig. Varje rättning syns i ändringsloggen med datum, källa och motivering.