<?xml version="1.0" encoding="utf-8" standalone="yes"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="da">
  <title>Engineer — Data — Portefølje og noter</title>
  <subtitle>Engineer ApS — softwareudvikling &amp; IT-rådgivning i København, Danmark. En portefølje af dokumenterede ingeniørresultater inden for software, data, cloud og IT.</subtitle>
  <id>https://data.engineer.company/da/</id>
  <updated>2026-09-13T15:01:29+02:00</updated>
  <author>
    <name>Engineer ApS</name>
    <uri>https://data.engineer.company/da/</uri>
    <email>welcome@engineer.company</email>
  </author>
  <rights>Copyright © 2025 – nu · Engineer ApS</rights>
  <generator uri="https://gohugo.io/">Hugo 0.166.0</generator>
  <icon>https://data.engineer.company/assets/icons/apple/apple-touch-icon.png</icon>
  <logo>https://data.engineer.company/assets/images/brand/card.webp</logo>
  <link href="https://data.engineer.company/da/" rel="alternate" type="text/html" />
  <link href="https://data.engineer.company/da/atom.xml" rel="self" type="application/atom+xml" />
  <entry>
    <title>Har øget brandengagement og -loyalitet med 100 % gennem analyse af markedstendenser og indsigt i forbrugeradfærd.</title>
    <id>https://data.engineer.company/da/portfolio/drove-brand-engagement-and-loyalty-by-100-through-2/</id>
    <link href="https://data.engineer.company/da/portfolio/drove-brand-engagement-and-loyalty-by-100-through-2/" rel="alternate" type="text/html" />
    <updated>2026-09-13T15:01:29+02:00</updated>
    <published>2026-09-13T15:01:29+02:00</published>
    <category term="Brand &amp; marketing" scheme="https://data.engineer.company/da/categories/" />
    <category term="Dataanalyse" scheme="https://data.engineer.company/da/categories/" />
    <category term="Produkt &amp; krav" scheme="https://data.engineer.company/da/categories/" />
    <category term="Stakeholder &amp; rapportering" scheme="https://data.engineer.company/da/categories/" />
    <category term="Brand, marketing &amp; SEO" scheme="https://data.engineer.company/da/services/" />
    <category term="Dataanalyse &amp; BI‑dashboards" scheme="https://data.engineer.company/da/services/" />
    <category term="Produktstrategi &amp; kravspecifikation" scheme="https://data.engineer.company/da/services/" />
    <summary>Fordoblede brandengagement og -loyalitet (+100 %) via analyse af markedstendenser og forbrugeradfærd — et publikum, der kom tilbage.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Situation.&lt;/strong&gt; Efterhånden som synligheden klatrede, nåede Engineer ApS flere mennesker — men engagementet var tyndt. Folk lagde mærke til det og gik videre; den tidlige interesse blev ikke til relationer, der holdt. Rækkevidde uden engagement er bare støj, og brandet lavede støj mere end forbindelser.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Opgave.&lt;/strong&gt; Målet var at uddybe engagementet og loyaliteten, og gøre det ved faktisk at kigge på, hvad markedet og publikummet reagerede på, frem for at stole på mavefornemmelse.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Handling.&lt;/strong&gt; Så brandet blev datainformeret i stedet for intuitionsstyret. Det betød at kigge på markedstendenserne og på, hvordan publikummet faktisk opførte sig på tværs af kanalerne — ikke hvad nogen antog, de ville kunne lide, men hvad de påviseligt engagerede sig i. Det afslørede de emner og formater, der trak ægte opmærksomhed, og indholdet og opsøgningen blev styret mod dem. Den vigtige del var at stramme loopet: se, hvad der landede, udgiv mere af den form næste gang, og lad hver cyklus være en smule bedre rettet end den forrige.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Resultat.&lt;/strong&gt; Engagement og loyalitet blev fordoblet — en forbedring på 100 % — med et publikum, der kom tilbage og engagerede sig frem for at kigge én gang og gå, og markant stærkere relationer til potentielle kunder og partnere. Brandet holdt op med at udsende ud i tomrummet og begyndte at opbygge noget, der kom tilbage.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Har designet en omfattende infrastrukturramme for DTU, der berører 14 afdelinger, med fleksible moduler, samlede datapipelines og strukturerede supportstrategier med henblik på langsigtet udbredelse.</title>
    <id>https://data.engineer.company/da/portfolio/designed-a-comprehensive-infrastructure-framework-for-dtu-impacting-3/</id>
    <link href="https://data.engineer.company/da/portfolio/designed-a-comprehensive-infrastructure-framework-for-dtu-impacting-3/" rel="alternate" type="text/html" />
    <updated>2026-09-13T15:01:29+02:00</updated>
    <published>2026-09-13T15:01:29+02:00</published>
    <category term="Data engineering" scheme="https://data.engineer.company/da/categories/" />
    <category term="Data governance" scheme="https://data.engineer.company/da/categories/" />
    <category term="Datapipelines (ETL/ELT)" scheme="https://data.engineer.company/da/categories/" />
    <category term="Dokumentation" scheme="https://data.engineer.company/da/categories/" />
    <category term="Infrastruktur" scheme="https://data.engineer.company/da/categories/" />
    <category term="Løsningsarkitektur" scheme="https://data.engineer.company/da/categories/" />
    <category term="Platformarkitektur" scheme="https://data.engineer.company/da/categories/" />
    <category term="Stakeholder &amp; rapportering" scheme="https://data.engineer.company/da/categories/" />
    <category term="Teknisk ledelse" scheme="https://data.engineer.company/da/categories/" />
    <category term="Data governance &amp; datakvalitet" scheme="https://data.engineer.company/da/services/" />
    <category term="Platform- &amp; løsningsarkitektur" scheme="https://data.engineer.company/da/services/" />
    <category term="Teknisk dokumentation" scheme="https://data.engineer.company/da/services/" />
    <category term="Teknisk ledelse &amp; rådgivning" scheme="https://data.engineer.company/da/services/" />
    <category term="Udvikling af datapipelines (ETL/ELT)" scheme="https://data.engineer.company/da/services/" />
    <summary>Designede en omfattende infrastrukturramme for DTU på tværs af 14 afdelinger — modulær, med samlede datapipelines og supportstrategier.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Situation.&lt;/strong&gt; På et forskningsinstitut bestående af 14 forskellige forskningsgrupper arbejdede hver gruppe med forskellige datakilder, formater, skalaer og softwareværktøjer. Den tekniske ekspertise og de tilgængelige IT‑ressourcer varierede meget på tværs af grupperne. Mens nogle få havde formået at skabe og udrulle skræddersyede IT‑løsninger, kæmpede mange med kompleksiteten af deres datainfrastrukturbehov, hvilket tog værdifuld tid og fokus fra deres kerneforskning.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Opgave.&lt;/strong&gt; Opgaven var at udtænke en løsning, der ville give forskerne mulighed for at fokusere på deres videnskabelige arbejde frem for IT‑udfordringer. Målet var at designe og implementere en skalerbar, institutdækkende datainfrastruktur, der kunne rumme de brede og forskelligartede behov hos størstedelen af forskningsgrupperne.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Handling.&lt;/strong&gt; En robust og fremtidssikret infrastrukturplan blev udviklet, der balancerede fleksibilitet og standardisering. Planen skitserede nøglekomponenter såsom modulær arkitektur, integrationsveje for forskellige datakilder, brugervenlige grænseflader tilpasset varierende tekniske niveauer samt skalerbare lagrings- og behandlingsløsninger. Den omfattede også strategier for onboarding, support og governance for at sikre udbredelse og bæredygtighed.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Resultat.&lt;/strong&gt; Den resulterende infrastrukturplan var både teknisk solid og strategisk afstemt med instituttets forskningsmål. Den forenede visionen for datahåndtering på tværs af organisationen, gav en klar vej til at reducere IT‑byrden på forskerne og lagde fundamentet for et fælles, effektivt og fremtidsklart forskningsdatamiljø. Planen blev vel modtaget for sin inklusivitet, klarhed og tilpasningsevne og satte en stærk retning for instituttets transformation af datainfrastrukturen.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Har udviklet en pipeline til timebaseret aggregering af elforbrug i Python / SQL / Bash &#43; Jq, der opnår 180 ms for 30‑dages datasæt på tværs af heterogene JSONL‑kilder.</title>
    <id>https://data.engineer.company/da/portfolio/engineered-hourly-electricity-consumption-aggregation-pipeline-in-python-4/</id>
    <link href="https://data.engineer.company/da/portfolio/engineered-hourly-electricity-consumption-aggregation-pipeline-in-python-4/" rel="alternate" type="text/html" />
    <updated>2026-09-13T15:01:29+02:00</updated>
    <published>2026-09-13T15:01:29+02:00</published>
    <category term="Automatisering &amp; CI/CD" scheme="https://data.engineer.company/da/categories/" />
    <category term="Data engineering" scheme="https://data.engineer.company/da/categories/" />
    <category term="Databaser" scheme="https://data.engineer.company/da/categories/" />
    <category term="Datapipelines (ETL/ELT)" scheme="https://data.engineer.company/da/categories/" />
    <category term="Dataanalyse" scheme="https://data.engineer.company/da/categories/" />
    <category term="Performanceoptimering" scheme="https://data.engineer.company/da/categories/" />
    <category term="PostgreSQL" scheme="https://data.engineer.company/da/categories/" />
    <category term="Python" scheme="https://data.engineer.company/da/categories/" />
    <category term="SQL" scheme="https://data.engineer.company/da/categories/" />
    <category term="Databaseoptimering" scheme="https://data.engineer.company/da/services/" />
    <category term="Dataanalyse &amp; BI‑dashboards" scheme="https://data.engineer.company/da/services/" />
    <category term="Udvikling af datapipelines (ETL/ELT)" scheme="https://data.engineer.company/da/services/" />
    <summary>Byggede en Python/SQL/Bash-pipeline til elforbrug, der aggregerer 30-dages datasæt på 180 ms på tværs af heterogene JSONL-kilder.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Situation.&lt;/strong&gt; Virksomheden behandler store mængder heterogene eldata fra flere datakilder, hver med sin egen rapporteringsfrekvens — fra timeintervaller til 15‑minutters intervaller og i nogle tilfælde uregelmæssige tidsstempler. Denne variabilitet gør det udfordrende at skabe et sammenhængende, sammenligneligt datasæt. For at understøtte præcis energianalyse skal disse data normaliseres til konsistente timeforbrugsværdier, aggregeret pr. zone.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Opgave.&lt;/strong&gt; Målet var at tage rå event‑data fra et historisk datasæt (i JSONL‑format) og konvertere det til timeafstemte elforbrugstal, struktureret som én række pr. time og pr. zone. Konkret indebar opgaven at afstemme tidsstemplede data til strikse timeintervaller, aggregere den samlede elproduktion inden for hvert interval, indregne grænseoverskridende udveksling ved at lægge import til og trække eksport fra, og udskrive de endelige værdier i et struktureret, skalerbart format. Løsningen skulle desuden være effektiv nok til at skalere over lange tidsvinduer (30+ dage) og på tværs af flere lande/zoner.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Handling.&lt;/strong&gt; Tre forskellige varianter af løsningen blev implementeret med henholdsvis Python, JQ (til JSON‑behandling på kommandolinjen) og SQL, hver optimeret til forskellige kontekster. Python blev valgt for sin fleksibilitet og evne til effektivt at håndtere in‑memory‑transformationer: en pipeline, der parser JSONL‑filerne, resampler tidsserien til timeintervaller, aggregerer produktion og beregner nettoelforbrug (produktion + import − eksport) og eksporterer resultaterne. JQ gav en hurtig løsning med minimale afhængigheder, og i PostgreSQL blev dataene importeret, normaliserede tabeller oprettet og en række SQL‑forespørgsler skrevet. For at vurdere ydeevnen blev hver løsning benchmarket med både 1‑dags og 30‑dages datasæt.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Resultat.&lt;/strong&gt; Python‑implementeringen viste sig som den hurtigste og mest skalerbare løsning og gennemførte 1‑dags databehandling på blot 34 ms og 30‑dages datasættet på 180 ms. Det bekræftede egnetheden til større tidsvinduer med sub‑sekund‑ydeevne og gav samtidig klar, vedligeholdelig kode, der let kunne udvides til flere zoner eller integreres i en ETL‑pipeline.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Har øget ydeevnen af geografiske datapipelines med 50 gange ved at forbedre SQL‑programmering og datamodellering på tværs af PostgreSQL, MS SQL og Google Cloud BigQuery.</title>
    <id>https://data.engineer.company/da/portfolio/accelerated-geographical-data-pipeline-performance-by-50x-by-5/</id>
    <link href="https://data.engineer.company/da/portfolio/accelerated-geographical-data-pipeline-performance-by-50x-by-5/" rel="alternate" type="text/html" />
    <updated>2026-09-13T15:01:29+02:00</updated>
    <published>2026-09-13T15:01:29+02:00</published>
    <category term="Data engineering" scheme="https://data.engineer.company/da/categories/" />
    <category term="Data governance" scheme="https://data.engineer.company/da/categories/" />
    <category term="Data warehousing" scheme="https://data.engineer.company/da/categories/" />
    <category term="Databaser" scheme="https://data.engineer.company/da/categories/" />
    <category term="Datapipelines (ETL/ELT)" scheme="https://data.engineer.company/da/categories/" />
    <category term="GIS / Geospatial" scheme="https://data.engineer.company/da/categories/" />
    <category term="Performanceoptimering" scheme="https://data.engineer.company/da/categories/" />
    <category term="PostgreSQL" scheme="https://data.engineer.company/da/categories/" />
    <category term="SQL" scheme="https://data.engineer.company/da/categories/" />
    <category term="Databaseoptimering" scheme="https://data.engineer.company/da/services/" />
    <category term="Design af data warehouse" scheme="https://data.engineer.company/da/services/" />
    <category term="GIS &amp; geospatiale løsninger" scheme="https://data.engineer.company/da/services/" />
    <category term="Udvikling af datapipelines (ETL/ELT)" scheme="https://data.engineer.company/da/services/" />
    <summary>Accelererede en geografisk datapipeline 50× via SQL- og datamodeloptimering på tværs af PostgreSQL, MS SQL og Google BigQuery.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Situation.&lt;/strong&gt; Organisationen oplevede betydelige forsinkelser i behandlingen af store mængder geografiske data, hvilket påvirkede effektiviteten af datadrevne beslutningsprocesser og analytisk rapportering.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Opgave.&lt;/strong&gt; Målet var at optimere den geografiske datapipeline for at forbedre ydeevnen og reducere behandlingstiden, så dataanalyse kunne udføres mere effektivt og i realtid.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Handling.&lt;/strong&gt; De eksisterende SQL‑programmerings- og datamodelleringsstrukturer på tværs af PostgreSQL, MS SQL og Google Cloud BigQuery blev analyseret grundigt, hvilket afslørede flaskehalse relateret til ineffektive indekseringsstrategier, suboptimale forespørgsler og manglende constraints. For at afhjælpe dette blev datamodellerne redesignet og partitioneringsstrategier indført, avancerede indekseringsteknikker (B‑tree og GiST i PostgreSQL, filtrerede indeks i MS SQL og clustering i BigQuery) anvendt, komplekse SQL‑forespørgsler optimeret ved at refaktorere subqueries og reducere joins, samt data integrity‑constraints som foreign keys og check‑constraints indført for at sikre konsistens uden at gå på kompromis med ydeevnen.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Resultat.&lt;/strong&gt; Disse omfattende optimeringer accelererede den geografiske datapipelines ydeevne 50 gange og reducerede databehandlingstiden markant. Forbedringen muliggjorde realtidsanalyse, styrkede rapporteringskapaciteten og gav interessenterne rettidige, datadrevne indsigter, hvilket i sidste ende bidrog til mere velfunderede strategiske beslutninger.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Har forbedret geografiske kortapplikationers ydeevne med 10 gange gennem en strategisk databaseovergang fra MSSQL til PostgreSQL, hvilket har optimeret behandlingen og datasikkerheden.</title>
    <id>https://data.engineer.company/da/portfolio/improved-geographical-map-application-performance-by-10x-through-6/</id>
    <link href="https://data.engineer.company/da/portfolio/improved-geographical-map-application-performance-by-10x-through-6/" rel="alternate" type="text/html" />
    <updated>2026-09-13T15:01:29+02:00</updated>
    <published>2026-09-13T15:01:29+02:00</published>
    <category term="Backend‑udvikling" scheme="https://data.engineer.company/da/categories/" />
    <category term="Data engineering" scheme="https://data.engineer.company/da/categories/" />
    <category term="Databaser" scheme="https://data.engineer.company/da/categories/" />
    <category term="Datapipelines (ETL/ELT)" scheme="https://data.engineer.company/da/categories/" />
    <category term="GIS / Geospatial" scheme="https://data.engineer.company/da/categories/" />
    <category term="Migrering &amp; modernisering" scheme="https://data.engineer.company/da/categories/" />
    <category term="Performanceoptimering" scheme="https://data.engineer.company/da/categories/" />
    <category term="PostgreSQL" scheme="https://data.engineer.company/da/categories/" />
    <category term="Sikkerhed" scheme="https://data.engineer.company/da/categories/" />
    <category term="SQL" scheme="https://data.engineer.company/da/categories/" />
    <category term="Databasemigrering &amp; modernisering" scheme="https://data.engineer.company/da/services/" />
    <category term="Databaseoptimering" scheme="https://data.engineer.company/da/services/" />
    <category term="GIS &amp; geospatiale løsninger" scheme="https://data.engineer.company/da/services/" />
    <summary>Forbedrede en GIS-kortapplikation 10× ved migrering fra MSSQL til PostgreSQL — spatiale forespørgsler fra 2,5 s til under 250 ms.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Situation.&lt;/strong&gt; Organisationens geografiske kortapplikation, der understøttede realtids‑spatialforespørgsler for mange brugere, oplevede alvorlige flaskehalse i ydeevnen. Latens ved rendering af kortlag og forespørgsler på lokationsbaserede data påvirkede både brugeroplevelsen og backend‑tjenesternes pålidelighed. Systemet byggede på en ældre Microsoft SQL Server‑database (MSSQL) uden native geospatial indeksering.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Opgave.&lt;/strong&gt; At forbedre kortapplikationens ydeevne, skalerbarhed og sikkerhed med det specifikke mål at reducere forespørgselslatensen og øge gennemløbet for spatiale operationer.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Handling.&lt;/strong&gt; En strategisk databasemigrering fra MSSQL til PostgreSQL med PostGIS‑udvidelsen blev ledet for at muliggøre native geospatial understøttelse. Et nyt skema optimeret til spatiale data blev designet med GiST- og SP‑GiST‑indeks på geometri- og geografikolonner, strikse foreign key- og check‑constraints defineret, over 50 millioner spatiale records migreret via ETL‑pipelines med transformation til nye SRID‑standarder (EPSG:4326), PostgreSQL‑konfigurationsparametre (work_mem, effective_cache_size) tunet og role‑based access control (RBAC) og row‑level security implementeret.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Resultat.&lt;/strong&gt; En 10‑dobbelt forbedring i spatial forespørgselsydeevne blev opnået, og den gennemsnitlige svartid reduceret fra 2,5 sekunder til under 250 millisekunder. Backend‑CPU‑belastningen faldt med 65 %, og systemtilgængeligheden blev bedre i spidsbelastningsperioder. Sikkerheden blev også styrket med granulære adgangspolitikker og valideringsconstraints, hvilket reducerede risikoen for korruption af spatiale data.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Har løst 1.000 problemer i geografiske data og tidsseriedata ved hjælp af GDAL, ArcGIS, PostGIS, Mapbox, QGIS, SQL (PL/pgSQL, Transact‑SQL) og Bash, hvilket har sikret behandling af big data i høj kvalitet.</title>
    <id>https://data.engineer.company/da/portfolio/resolved-1-000-issues-in-geographical-data-and-7/</id>
    <link href="https://data.engineer.company/da/portfolio/resolved-1-000-issues-in-geographical-data-and-7/" rel="alternate" type="text/html" />
    <updated>2026-09-13T15:01:29+02:00</updated>
    <published>2026-09-13T15:01:29+02:00</published>
    <category term="Automatisering &amp; CI/CD" scheme="https://data.engineer.company/da/categories/" />
    <category term="Data engineering" scheme="https://data.engineer.company/da/categories/" />
    <category term="Data governance" scheme="https://data.engineer.company/da/categories/" />
    <category term="Databaser" scheme="https://data.engineer.company/da/categories/" />
    <category term="Datapipelines (ETL/ELT)" scheme="https://data.engineer.company/da/categories/" />
    <category term="GIS / Geospatial" scheme="https://data.engineer.company/da/categories/" />
    <category term="Performanceoptimering" scheme="https://data.engineer.company/da/categories/" />
    <category term="PostgreSQL" scheme="https://data.engineer.company/da/categories/" />
    <category term="SQL" scheme="https://data.engineer.company/da/categories/" />
    <category term="Data governance &amp; datakvalitet" scheme="https://data.engineer.company/da/services/" />
    <category term="GIS &amp; geospatiale løsninger" scheme="https://data.engineer.company/da/services/" />
    <category term="Udvikling af datapipelines (ETL/ELT)" scheme="https://data.engineer.company/da/services/" />
    <summary>Løste 1.000+ problemer i geografiske og tidsseriedata med GDAL, PostGIS, ArcGIS, Mapbox, QGIS og SQL — 35 % hurtigere forespørgsler.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Situation.&lt;/strong&gt; Under arbejdet på et storstilet geospatialt analyseprojekt stødte teamet på talrige uoverensstemmelser og anomalier i de geografiske datasæt og tidsseriedatasæt. Disse problemer påvirkede nøjagtigheden af spatiale analyser og beslutningsværktøjer på tværs af flere afdelinger.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Opgave.&lt;/strong&gt; Ansvaret var at identificere, løse og optimere over 1.000 datakvalitetsproblemer i disse komplekse datasæt for at sikre integriteten og ydeevnen af downstream‑applikationer og visualiseringer.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Handling.&lt;/strong&gt; Spatiale fejl blev systematisk diagnosticeret og rettet med en kombination af værktøjer, herunder GDAL, QGIS og ArcGIS, og automatiserede workflows implementeret med Bash‑scripting til tilbagevendende datarensning. PostGIS blev brugt til avancerede spatiale forespørgsler og spatial indeksering, og robuste procedurer skrevet i PL/pgSQL og Transact‑SQL til at håndtere og transformere både geografiske og tidsmæssige data i PostgreSQL- og SQL Server‑databaserne. Derudover blev de rensede data integreret i interaktive visualiseringer med Mapbox.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Resultat.&lt;/strong&gt; Gennem denne indsats blev over 1.000 kritiske problemer løst, hvilket markant forbedrede datanøjagtigheden og behandlingshastigheden. Det bidrog direkte til en 35 % reduktion i køretider for spatiale forespørgsler og muliggjorde mere pålidelige spatiale analyser. Arbejdet sikrede, at data af høj kvalitet konsekvent var tilgængelige til analyse og rapportering til støtte for strategiske beslutninger på tværs af organisationen.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Har designet, implementeret og administreret 6 ETL/ELT‑pipelines med Google BigQuery, MSSQL, PostgreSQL, shell‑scripting, PL/pgSQL og Transact‑SQL og integreret data til effektiv behandling via Python API.</title>
    <id>https://data.engineer.company/da/portfolio/designed-implemented-and-administered-6-etl-elt-pipelines-8/</id>
    <link href="https://data.engineer.company/da/portfolio/designed-implemented-and-administered-6-etl-elt-pipelines-8/" rel="alternate" type="text/html" />
    <updated>2026-09-13T15:01:29+02:00</updated>
    <published>2026-09-13T15:01:29+02:00</published>
    <category term="Automatisering &amp; CI/CD" scheme="https://data.engineer.company/da/categories/" />
    <category term="Cloud" scheme="https://data.engineer.company/da/categories/" />
    <category term="Data engineering" scheme="https://data.engineer.company/da/categories/" />
    <category term="Data warehousing" scheme="https://data.engineer.company/da/categories/" />
    <category term="Databaser" scheme="https://data.engineer.company/da/categories/" />
    <category term="Datapipelines (ETL/ELT)" scheme="https://data.engineer.company/da/categories/" />
    <category term="Netværk &amp; VPN" scheme="https://data.engineer.company/da/categories/" />
    <category term="PostgreSQL" scheme="https://data.engineer.company/da/categories/" />
    <category term="Python" scheme="https://data.engineer.company/da/categories/" />
    <category term="SQL" scheme="https://data.engineer.company/da/categories/" />
    <category term="Backend- &amp; API‑udvikling" scheme="https://data.engineer.company/da/services/" />
    <category term="Databasedesign &amp; datamodellering" scheme="https://data.engineer.company/da/services/" />
    <category term="Design af data warehouse" scheme="https://data.engineer.company/da/services/" />
    <category term="Udvikling af datapipelines (ETL/ELT)" scheme="https://data.engineer.company/da/services/" />
    <summary>Designede og driftede 6 ETL/ELT-pipelines (BigQuery, MSSQL, PostgreSQL) — fra 3 timers manuelt arbejde til under 20 minutter, dagligt.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Situation.&lt;/strong&gt; Organisationen havde behov for at konsolidere og behandle store mængder strukturerede data fra et fjernt data warehouse bag en IPSec VPN. Disse data var afgørende for interne analyse‑dashboards og eksterne Python API&amp;rsquo;er brugt af kunder og partnere.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Opgave.&lt;/strong&gt; Målet var at designe, implementere og vedligeholde et sæt robuste og automatiserede ETL/ELT‑pipelines til sikkert at hente, transformere og indlæse data i Google BigQuery med sikring af datanøjagtighed, ydeevne og skalerbarhed.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Handling.&lt;/strong&gt; 6 end‑to‑end ETL/ELT‑pipelines blev designet, implementeret og administreret på tværs af Google BigQuery, MSSQL, PostgreSQL, shell‑scripting, PL/pgSQL og Transact‑SQL. Sikre forbindelser til en fjernserver bag en IPSec VPN blev etableret, download af komprimerede dataarkiver (Parquet, CSV og .bak) planlagt, Bash- og Python‑scripts udviklet til at udtrække og klassificere filer, .bak‑filer gendannet i en lokal MSSQL Server‑instans, strukturerede data indlæst i staging‑skemaer med bcp, psql og SSIS, modulære PL/pgSQL- og T‑SQL‑procedurer skrevet til rensning og berigelse og upload og skema‑mapping til Google BigQuery automatiseret via bq CLI og Python‑baseret dataindtagelse.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Resultat.&lt;/strong&gt; Disse automatiserede pipelines reducerede den manuelle indsats og behandlingstid markant — fra over 3 timers manuelt arbejde til under 20 minutter end‑to‑end — og forbedrede dataaktualiteten fra ugentlig til daglig synkronisering. Python‑API&amp;rsquo;erne, der forbrugte dataene, opnåede en 30 % ydeevneforbedring, og den øgede synlighed hjalp forretningsanalytikere med at levere hurtigere indsigter. Løsningen forbliver skalerbar og udvidelig til nye datakilder, efterhånden som forretningen vokser.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Har udviklet og lanceret virksomhedens første observability‑dashboard, der leverer indsigt i systemets ydeevne i realtid og datavisualisering på det store kontor‑TV.</title>
    <id>https://data.engineer.company/da/portfolio/developed-and-launched-the-company-s-first-observability-9/</id>
    <link href="https://data.engineer.company/da/portfolio/developed-and-launched-the-company-s-first-observability-9/" rel="alternate" type="text/html" />
    <updated>2026-09-13T15:01:29+02:00</updated>
    <published>2026-09-13T15:01:29+02:00</published>
    <category term="Automatisering &amp; CI/CD" scheme="https://data.engineer.company/da/categories/" />
    <category term="Containere (Docker/Kubernetes)" scheme="https://data.engineer.company/da/categories/" />
    <category term="Dataanalyse" scheme="https://data.engineer.company/da/categories/" />
    <category term="DevOps" scheme="https://data.engineer.company/da/categories/" />
    <category term="Drift &amp; backup" scheme="https://data.engineer.company/da/categories/" />
    <category term="Infrastruktur" scheme="https://data.engineer.company/da/categories/" />
    <category term="Linux &amp; servere" scheme="https://data.engineer.company/da/categories/" />
    <category term="Monitorering &amp; observability" scheme="https://data.engineer.company/da/categories/" />
    <category term="Dataanalyse &amp; BI‑dashboards" scheme="https://data.engineer.company/da/services/" />
    <category term="Site reliability &amp; monitorering" scheme="https://data.engineer.company/da/services/" />
    <summary>Byggede virksomhedens første observability-dashboard til realtidsindsigt — teams opdagede og løste incidents 40 % hurtigere.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Situation.&lt;/strong&gt; Virksomheden havde udfordringer med at overvåge systemets ydeevne i realtid, hvilket ofte førte til forsinket incidenthåndtering og reduceret indblik i infrastrukturens tilstand. Der fandtes ingen central løsning, hvor teams kunne få indsigt i driftsmetrikker.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Opgave.&lt;/strong&gt; Opgaven var at udvikle en løsning, der ville gøre det muligt for både tekniske og ikke‑tekniske interessenter at overvåge centrale systemmetrikker i realtid med fokus på tilgængelighed, klarhed og proaktiv fejlopsporing.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Handling.&lt;/strong&gt; Virksomhedens første observability‑dashboard blev designet og implementeret og indsamlede alle væsentlige systemmetrikker — CPU, RAM, HDD, temperatur med mere — fra fjerne Linux‑servere via SSH, og selv Docker‑containere blev overvåget på denne måde. Senere blev en anden version designet og implementeret med Grafana og Prometheus til mere avanceret visualisering. Samarbejde med DevOps- og engineering‑teams identificerede kritiske metrikker, datapipelines blev konfigureret til at indsamle og behandle ydeevnemetrikker, og dashboardet udrullet på en stor kontor‑TV‑skærm for maksimal synlighed. Alarmering ved overskridelse af tærskler blev også integreret.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Resultat.&lt;/strong&gt; Dashboardet forbedrede markant systemets gennemsigtighed og responstiden på driftsproblemer. Teams kunne opdage og løse incidents 40 % hurtigere. Det fremmede også en kultur af fælles ejerskab over systemets tilstand ved at gøre ydeevnedata tilgængelige for alle på kontoret, hvilket i sidste ende bidrog til et mere stabilt og effektivt produktionsmiljø.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Har leveret 8 Power BI‑projekter med omfattende manualer, hvor Microsoft Power BI‑værktøjer er integreret med NodeJS API og Python FastAPI for effektiv dataanalyse og visualisering.</title>
    <id>https://data.engineer.company/da/portfolio/delivered-8-power-bi-projects-with-comprehensive-manuals-10/</id>
    <link href="https://data.engineer.company/da/portfolio/delivered-8-power-bi-projects-with-comprehensive-manuals-10/" rel="alternate" type="text/html" />
    <updated>2026-09-13T15:01:29+02:00</updated>
    <published>2026-09-13T15:01:29+02:00</published>
    <category term="API&#39;er &amp; integration" scheme="https://data.engineer.company/da/categories/" />
    <category term="Backend‑udvikling" scheme="https://data.engineer.company/da/categories/" />
    <category term="Data engineering" scheme="https://data.engineer.company/da/categories/" />
    <category term="Dataanalyse" scheme="https://data.engineer.company/da/categories/" />
    <category term="Dokumentation" scheme="https://data.engineer.company/da/categories/" />
    <category term="GIS / Geospatial" scheme="https://data.engineer.company/da/categories/" />
    <category term="Produkt &amp; krav" scheme="https://data.engineer.company/da/categories/" />
    <category term="Python" scheme="https://data.engineer.company/da/categories/" />
    <category term="Backend- &amp; API‑udvikling" scheme="https://data.engineer.company/da/services/" />
    <category term="Dataanalyse &amp; BI‑dashboards" scheme="https://data.engineer.company/da/services/" />
    <category term="Teknisk dokumentation" scheme="https://data.engineer.company/da/services/" />
    <summary>Leverede 8 Power BI-analyseprojekter (Node.js API, Python FastAPI) med manualer — 60 % mere effektiv rapportgenerering.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Situation.&lt;/strong&gt; Organisationen havde behov for dynamiske, visuelle indsigter i komplekse datasæt om elnettets ydeevne og geografisk fordeling for at understøtte beslutninger på tværs af tekniske og strategiske teams.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Opgave.&lt;/strong&gt; At udvikle interaktive dashboards og rapporteringsløsninger, der effektivt kunne præsentere både realtids- og historiske geografiske og elektriske data, så interessenter hurtigt kunne identificere tendenser, anomalier og nøgletal.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Handling.&lt;/strong&gt; Microsoft Power BI blev integreret med en skræddersyet backend baseret på NodeJS API og Python FastAPI for at strømline dataindtagelse, transformation og visualisering. Dashboards blev designet og implementeret med kortvisualiseringer, målinger af energiforbrug, sporing af nedbrud og indikatorer for neteffektivitet, og genanvendelige skabeloner og detaljeret dokumentation udviklet for at understøtte skalerbarhed og brugervenlighed.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Resultat.&lt;/strong&gt; 8 dataanalyseprojekter blev leveret, hvilket forbedrede effektiviteten af rapportgenerering med 60 % og gjorde det muligt for tværfaglige teams at træffe hurtigere, datadrevne beslutninger. Interessenterne rapporterede en markant øget forståelse af den regionale elektriske ydeevne og nøjagtigheden af ressourceplanlægningen.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Har udgivet 500 rapporter om analyse af el- og GIS‑data, hvor jeg har anvendt dybdegående forskning og fejlfinding for at sikre nøjagtige geografiske og tidsmæssige big data‑indsigter.</title>
    <id>https://data.engineer.company/da/portfolio/released-500-electricity-and-gis-data-analysis-reports-11/</id>
    <link href="https://data.engineer.company/da/portfolio/released-500-electricity-and-gis-data-analysis-reports-11/" rel="alternate" type="text/html" />
    <updated>2026-09-13T15:01:29+02:00</updated>
    <published>2026-09-13T15:01:29+02:00</published>
    <category term="Data governance" scheme="https://data.engineer.company/da/categories/" />
    <category term="Data warehousing" scheme="https://data.engineer.company/da/categories/" />
    <category term="Databaser" scheme="https://data.engineer.company/da/categories/" />
    <category term="Dataanalyse" scheme="https://data.engineer.company/da/categories/" />
    <category term="Dokumentation" scheme="https://data.engineer.company/da/categories/" />
    <category term="GIS / Geospatial" scheme="https://data.engineer.company/da/categories/" />
    <category term="PostgreSQL" scheme="https://data.engineer.company/da/categories/" />
    <category term="SQL" scheme="https://data.engineer.company/da/categories/" />
    <category term="Stakeholder &amp; rapportering" scheme="https://data.engineer.company/da/categories/" />
    <category term="Data governance &amp; datakvalitet" scheme="https://data.engineer.company/da/services/" />
    <category term="Dataanalyse &amp; BI‑dashboards" scheme="https://data.engineer.company/da/services/" />
    <category term="GIS &amp; geospatiale løsninger" scheme="https://data.engineer.company/da/services/" />
    <summary>Udgav 500 rapporter om el- og GIS-dataanalyse — en tværgående reference for load balancing, energieffektivitet og anomalidetektion.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Situation.&lt;/strong&gt; Teamet håndterede enorme datasæt genereret af smart‑metre installeret på tværs af flere geografiske regioner. Disse smart‑metre producerede granulære tidsserie‑data om elforbrug, som blev brugt af energianalytikere, ingeniører og regionale planlæggere til drifts- og strategiske beslutninger.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Opgave.&lt;/strong&gt; Ansvaret var at producere analytiske rapporter af høj kvalitet, gennemsigtige og reproducerbare, som kunne afdække mønstre i energiforbruget, opdage anomalier og identificere regionale forbrugstendenser, samtidig med at ikke‑tekniske interessenter let kunne fortolke og genbruge resultaterne.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Handling.&lt;/strong&gt; Over 500 dybdegående dataanalyserapporter blev oprettet og leveret, med ren SQL til al dataudtræk, transformation og analyse direkte i cloud‑baserede miljøer som PostgreSQL og BigQuery. Dataene omfattede geolokationskoordinater, meter‑ID&amp;rsquo;er, tidsstemplet energiforbrug og miljømetadata. SQL‑scripts benyttede CTE&amp;rsquo;er, window functions, subqueries og geospatiale joins for skalerbar og effektiv behandling. Hver rapport indeholdt annoteret SQL‑kode, så kolleger fuldt ud kunne reproducere og revidere forskningen, og fejlfindingsnoter blev tilføjet og almindelige datakvalitetsproblemer dokumenteret med anbefalede håndteringsprocedurer.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Resultat.&lt;/strong&gt; Rapporterne blev en standardreference på tværs af afdelinger og hjalp med regional load balancing, planlægning af energieffektivitet og anomalidetektion. Ved at sikre fuld gennemsigtighed og reproducerbarhed hjalp det med at styrke interessenternes tillid til dataene, og arbejdet bidrog til mere præcise prognosemodeller og en 10–15 % forbedring af driftsplanlægningens effektivitet.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Har arkitekteret, oprettet og administreret 100 data warehouse‑databaser i PostgreSQL, MS SQL og Google BigQuery med primært GIS- og tidsseriedata og optimeret ydeevne og skalerbarhed.</title>
    <id>https://data.engineer.company/da/portfolio/architected-created-and-managed-100-postgresql-ms-sql-12/</id>
    <link href="https://data.engineer.company/da/portfolio/architected-created-and-managed-100-postgresql-ms-sql-12/" rel="alternate" type="text/html" />
    <updated>2026-09-13T15:01:29+02:00</updated>
    <published>2026-09-13T15:01:29+02:00</published>
    <category term="Data engineering" scheme="https://data.engineer.company/da/categories/" />
    <category term="Data governance" scheme="https://data.engineer.company/da/categories/" />
    <category term="Data warehousing" scheme="https://data.engineer.company/da/categories/" />
    <category term="Databaser" scheme="https://data.engineer.company/da/categories/" />
    <category term="Drift &amp; backup" scheme="https://data.engineer.company/da/categories/" />
    <category term="GIS / Geospatial" scheme="https://data.engineer.company/da/categories/" />
    <category term="Performanceoptimering" scheme="https://data.engineer.company/da/categories/" />
    <category term="Platformarkitektur" scheme="https://data.engineer.company/da/categories/" />
    <category term="PostgreSQL" scheme="https://data.engineer.company/da/categories/" />
    <category term="SQL" scheme="https://data.engineer.company/da/categories/" />
    <category term="Databaseadministration (DBA)" scheme="https://data.engineer.company/da/services/" />
    <category term="Databasedesign &amp; datamodellering" scheme="https://data.engineer.company/da/services/" />
    <category term="Databaseoptimering" scheme="https://data.engineer.company/da/services/" />
    <category term="Design af data warehouse" scheme="https://data.engineer.company/da/services/" />
    <category term="GIS &amp; geospatiale løsninger" scheme="https://data.engineer.company/da/services/" />
    <summary>Arkitekterede og driftede 100 data warehouse-databaser (PostgreSQL, MS SQL, BigQuery) for GIS- og tidsseriedata — 40–60 % hurtigere.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Situation.&lt;/strong&gt; I en hurtigt voksende teknologivirksomhed var der et kritisk behov for at oprette, administrere og optimere en bred portefølje af over 100 databaser på tværs af PostgreSQL, Microsoft SQL Server og Google BigQuery. Disse databaser håndterede primært komplekse datasæt, herunder GIS‑data (spatiale koordinater og lokationsbaseret analyse) og tidsseriedata (sensoraflæsninger, logs og realtidsmetrikker). Den eksisterende infrastruktur havde udfordringer med skalerbarhed, forespørgselsydeevne og datakonsistens, efterhånden som datamængden voksede eksponentielt.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Opgave.&lt;/strong&gt; Det primære mål var at designe, implementere og administrere et skalerbart data warehouse‑økosystem med høj ydeevne skræddersyet til GIS- og tidsseriedata. Det indebar at håndtere flaskehalse i komplekse spatiale og tidsbaserede forespørgsler, sikre skalerbarhed og omkostningseffektivitet og samarbejde med tværfaglige teams om at afstemme databasedesign med forretningsbehov.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Handling.&lt;/strong&gt; Skalerbare arkitekturer blev designet med normaliserede og denormaliserede skemaer til PostgreSQL og SQL Server, spatial indeksering (PostGIS) og tidsseriepartitionering udnyttet samt BigQuerys tidspartitionerede og clustrede tabeller. Optimeringsstrategier som indeksering, materialized views og caching blev indført, datakomprimering og kolonnelagring anvendt i BigQuery og best practices for GIS- og tidsseriedatamodellering dokumenteret til fremtidige projekter.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Resultat.&lt;/strong&gt; Initiativerne førte til betydelige forbedringer: svartider for GIS- og tidsseriedata faldt med 40–60 %, automatiseret overvågning reducerede nedetid med 50 %, og standardiserede processer øgede produktiviteten. Den optimerede infrastruktur gjorde det muligt for virksomheden at lancere nye datadrevne produkter og opfylde krav om data governance og regulatorisk compliance — hvilket styrkede organisationens evne til at håndtere komplekse datamæssige udfordringer.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Har designet, idriftsat og vedligeholdt 10 PostgreSQL- og MS SQL‑servere på Ubuntu Linux VPS og sikret optimal serverydeevne og pålidelighed.</title>
    <id>https://data.engineer.company/da/portfolio/designed-deployed-and-maintained-10-postgresql-and-ms-13/</id>
    <link href="https://data.engineer.company/da/portfolio/designed-deployed-and-maintained-10-postgresql-and-ms-13/" rel="alternate" type="text/html" />
    <updated>2026-09-13T15:01:29+02:00</updated>
    <published>2026-09-13T15:01:29+02:00</published>
    <category term="Automatisering &amp; CI/CD" scheme="https://data.engineer.company/da/categories/" />
    <category term="Databaser" scheme="https://data.engineer.company/da/categories/" />
    <category term="DevOps" scheme="https://data.engineer.company/da/categories/" />
    <category term="Drift &amp; backup" scheme="https://data.engineer.company/da/categories/" />
    <category term="Infrastruktur" scheme="https://data.engineer.company/da/categories/" />
    <category term="Linux &amp; servere" scheme="https://data.engineer.company/da/categories/" />
    <category term="Monitorering &amp; observability" scheme="https://data.engineer.company/da/categories/" />
    <category term="Performanceoptimering" scheme="https://data.engineer.company/da/categories/" />
    <category term="PostgreSQL" scheme="https://data.engineer.company/da/categories/" />
    <category term="Sikkerhed" scheme="https://data.engineer.company/da/categories/" />
    <category term="Systemadministration" scheme="https://data.engineer.company/da/categories/" />
    <category term="Databaseadministration (DBA)" scheme="https://data.engineer.company/da/services/" />
    <category term="Site reliability &amp; monitorering" scheme="https://data.engineer.company/da/services/" />
    <category term="Systemadministration" scheme="https://data.engineer.company/da/services/" />
    <summary>Designede og vedligeholdt 10 PostgreSQL- og MS SQL-servere på Ubuntu Linux VPS med 99,9 % oppetid og 30 % hurtigere forespørgsler.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Situation.&lt;/strong&gt; Som DevOps‑ingeniør i en mellemstor teknologivirksomhed var opgaven at administrere og optimere databaseinfrastrukturen til støtte for en voksende brugerbase og forretningskritiske applikationer. Organisationen var stærkt afhængig af PostgreSQL og Microsoft SQL Server og krævede høj tilgængelighed, skalerbarhed og sikkerhed.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Opgave.&lt;/strong&gt; Det primære ansvar var at arkitektere, udrulle, konfigurere og vedligeholde 10 PostgreSQL- og MS SQL Server‑instanser i Ubuntu Linux VPS‑miljøer med optimal ydeevne, robuste sikkerhedsprotokoller og proaktiv overvågning, samt at skalere infrastrukturen til fremtidig vækst uden at gå på kompromis med omkostninger og compliance.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Handling.&lt;/strong&gt; PostgreSQL 14 og MS SQL Server 2019 blev installeret og konfigureret på Ubuntu 20.04 LTS, automatiserede backups sat op med pg_dump og SQL Server Agent‑jobs med retention og offsite‑lagring, og serverkonfigurationer optimeret (hukommelsesallokering, query caching, connection pooling). Overvågning blev implementeret med Prometheus og Grafana, regelmæssig patching af databaser og OS udført, firewalls (UFW) og RBAC konfigureret og disaster recovery‑procedurer dokumenteret, herunder point‑in‑time‑gendannelse og failover.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Resultat.&lt;/strong&gt; 99,9 % oppetid blev opnået på tværs af alle 10 databaseservere, svartider forbedret med 30 % gennem konfigurationstuning og indeksoptimering, manuelt vedligeholdelsesarbejde reduceret med 50 % via automatisering (over 10 timer om måneden frigjort) og infrastrukturen skaleret til at understøtte en 40 % stigning i brugertrafik uden servicetab — hvilket bidrog til 20 % omsætningsvækst i det følgende kvartal. CTO&amp;rsquo;en anerkendte implementeringen af sikkerheds‑best‑practices, der forhindrede potentielle databrud.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Har forbedret datasikkerheden ved at implementere 1.000 RBAC‑regler for udviklere, applikationsinstanser, PostgreSQL, MS SQL og andre Linux‑servere for at forhindre uautoriseret adgang; dokumenteret med Ansible‑automatisering.</title>
    <id>https://data.engineer.company/da/portfolio/enhanced-data-security-by-implementing-1-000-rbac-14/</id>
    <link href="https://data.engineer.company/da/portfolio/enhanced-data-security-by-implementing-1-000-rbac-14/" rel="alternate" type="text/html" />
    <updated>2026-09-13T15:01:29+02:00</updated>
    <published>2026-09-13T15:01:29+02:00</published>
    <category term="Automatisering &amp; CI/CD" scheme="https://data.engineer.company/da/categories/" />
    <category term="Databaser" scheme="https://data.engineer.company/da/categories/" />
    <category term="DevOps" scheme="https://data.engineer.company/da/categories/" />
    <category term="Dokumentation" scheme="https://data.engineer.company/da/categories/" />
    <category term="Infrastruktur" scheme="https://data.engineer.company/da/categories/" />
    <category term="Linux &amp; servere" scheme="https://data.engineer.company/da/categories/" />
    <category term="Sikkerhed" scheme="https://data.engineer.company/da/categories/" />
    <category term="Systemadministration" scheme="https://data.engineer.company/da/categories/" />
    <category term="Databaseadministration (DBA)" scheme="https://data.engineer.company/da/services/" />
    <category term="Infrastructure as Code" scheme="https://data.engineer.company/da/services/" />
    <category term="Sikkerhed &amp; adgangsstyring" scheme="https://data.engineer.company/da/services/" />
    <category term="Systemadministration" scheme="https://data.engineer.company/da/services/" />
    <summary>Styrkede datasikkerheden med 1.000 RBAC-regler på tværs af udviklere, apps og Linux/DB-servere — 85 % lavere adgangsrisiko, Ansible-drevet.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Situation.&lt;/strong&gt; Organisationen havde behov for at styrke adgangskontrollen på tværs af flere systemer, herunder udviklermiljøer, applikationsinstanser, PostgreSQL, MS SQL og Linux‑servere. Selvom den underliggende RBAC‑model var enkel, lå udfordringen i at håndtere over 1.000 individuelle regler for forskellige brugerroller og systemkrav uden at introducere kompleksitet.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Opgave.&lt;/strong&gt; At implementere en skalerbar RBAC‑løsning ved at definere og håndhæve over 1.000 regler for adgangskontrol. Det indebar at mappe rettigheder til specifikke roller (udviklere, applikationsinstanser, databaseadministratorer) og at anvende reglerne konsistent på tværs af alle systemer, samt at dokumentere reglerne og automatisere deres udrulning.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Handling.&lt;/strong&gt; Tilgangen fokuserede på at skabe en enkel, modulær RBAC‑struktur, med rettigheder brudt ned i klare, genanvendelige kategorier (f.eks. &amp;ldquo;read‑only‑adgang til produktionsdatabaser&amp;rdquo;). Med Ansible blev konfigurationen af hver regel automatiseret og konsistens sikret på tværs af miljøer: udviklere fik kun adgang til deres tildelte servere, mens applikationsinstanser havde begrænsede rettigheder for at forhindre lateral bevægelse. Processen prioriterede klarhed frem for kompleksitet, med hver regel eksplicit knyttet til en rolle og et system.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Resultat.&lt;/strong&gt; Implementeringen sikrede over 1.000 regler uden unødvendig kompleksitet og reducerede risikoen for uautoriseret adgang med 85 %. Automatiseringen strømlinede udrulningen og reducerede opsætningstiden med 60 % sammenlignet med manuelle metoder. Den dokumenterede ramme gjorde det muligt for teams hurtigt at revidere eller ændre regler og sikrede skalerbarhed, efterhånden som infrastrukturen voksede.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Har accelereret PostgreSQL‑ydeevnen 10 gange via strategisk indeksering, partitionering og query‑optimering og forbedret databaseeffektiviteten for bruger-, tenant-, geospatiale og tidsserie‑eldata.</title>
    <id>https://data.engineer.company/da/portfolio/accelerated-postgresql-performance-by-10x-via-strategic-indexing-15/</id>
    <link href="https://data.engineer.company/da/portfolio/accelerated-postgresql-performance-by-10x-via-strategic-indexing-15/" rel="alternate" type="text/html" />
    <updated>2026-09-13T15:01:29+02:00</updated>
    <published>2026-09-13T15:01:29+02:00</published>
    <category term="Data engineering" scheme="https://data.engineer.company/da/categories/" />
    <category term="Databaser" scheme="https://data.engineer.company/da/categories/" />
    <category term="GIS / Geospatial" scheme="https://data.engineer.company/da/categories/" />
    <category term="Performanceoptimering" scheme="https://data.engineer.company/da/categories/" />
    <category term="PostgreSQL" scheme="https://data.engineer.company/da/categories/" />
    <category term="SQL" scheme="https://data.engineer.company/da/categories/" />
    <category term="Databaseadministration (DBA)" scheme="https://data.engineer.company/da/services/" />
    <category term="Databaseoptimering" scheme="https://data.engineer.company/da/services/" />
    <summary>Accelererede PostgreSQL 10× via indeksering, partitionering og query-tuning for bruger-, tenant-, geospatiale og tidsseriedata — ressourceforbrug ned 40 %.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Situation.&lt;/strong&gt; PostgreSQL‑databasen betjente en mellemstor applikation, der håndterede brugerkonti, tenant‑oplysninger, geografiske data (lokationer, regioner) og daglige elforbrugsmetrikker. Mens systemet kørte under lav belastning, opstod der ydeevneproblemer, efterhånden som datamængderne voksede. Forespørgsler på geospatiale data og tidsserie‑ellogs blev langsomme, og mangel på optimeret indeksering, fragmenterede forespørgsler og upartitionerede tabeller forværrede problemet.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Opgave.&lt;/strong&gt; Målet var at forbedre databasens ydeevne 10 gange uden at ændre den eksisterende arkitektur. Fokus var på at optimere forespørgselsudførelse, reducere latens og sikre skalerbarhed til fremtidig datavækst, herunder bedre svartider for geospatiale og tidsbaserede forespørgsler og bevaret dataintegritet.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Handling.&lt;/strong&gt; Indeksering: Ofte forespurgte kolonner blev analyseret og målrettede indeks oprettet, herunder GiST‑indeks til geospatiale data og composite‑indeks til flerkolonnefiltre. Partitionering: Tidsbaseret range‑partitionering af eltabellen (pr. dag/måned) og hash‑partitionering af geografiske data blev implementeret. Query‑optimering: Komplekse forespørgsler blev omskrevet for at undgå full table scans, CTE&amp;rsquo;er og materialized views brugt, ineffektive joins identificeret med EXPLAIN ANALYZE og query caching og connection pooling konfigureret.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Resultat.&lt;/strong&gt; Efter optimeringen forbedredes svartiderne 10 gange, med kritiske operationer (brugerautentifikation, geospatiale opslag) på millisekunder. Databasens ressourceforbrug faldt med 40 %, så systemet kunne håndtere øgede datamængder uden ydeevnetab. Brugerne oplevede mere flydende interaktioner, systemet blev mere skalerbart, og ændringerne reducerede behovet for hardwareopgraderinger og sparede omkostninger.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Har automatiseret udrulning af GIS SaaS‑applikationer, databehandling og rapporteringssystem ved hjælp af GitHub Actions CI/CD, Python, Bash og SQL.</title>
    <id>https://data.engineer.company/da/portfolio/automated-gis-saas-application-deployment-data-processing-and-16/</id>
    <link href="https://data.engineer.company/da/portfolio/automated-gis-saas-application-deployment-data-processing-and-16/" rel="alternate" type="text/html" />
    <updated>2026-09-13T15:01:29+02:00</updated>
    <published>2026-09-13T15:01:29+02:00</published>
    <category term="Automatisering &amp; CI/CD" scheme="https://data.engineer.company/da/categories/" />
    <category term="Cloud" scheme="https://data.engineer.company/da/categories/" />
    <category term="Data engineering" scheme="https://data.engineer.company/da/categories/" />
    <category term="Datapipelines (ETL/ELT)" scheme="https://data.engineer.company/da/categories/" />
    <category term="DevOps" scheme="https://data.engineer.company/da/categories/" />
    <category term="Drift &amp; backup" scheme="https://data.engineer.company/da/categories/" />
    <category term="GIS / Geospatial" scheme="https://data.engineer.company/da/categories/" />
    <category term="Python" scheme="https://data.engineer.company/da/categories/" />
    <category term="SQL" scheme="https://data.engineer.company/da/categories/" />
    <category term="DevOps &amp; CI/CD‑automatisering" scheme="https://data.engineer.company/da/services/" />
    <category term="GIS &amp; geospatiale løsninger" scheme="https://data.engineer.company/da/services/" />
    <category term="Udvikling af datapipelines (ETL/ELT)" scheme="https://data.engineer.company/da/services/" />
    <summary>Automatiserede GIS SaaS-udrulning, databehandling og rapportering med GitHub Actions CI/CD, Python, Bash og SQL — pålidelige releases.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Situation.&lt;/strong&gt; Hos Utiligize var det at få GIS SaaS‑appen udrullet, behandle dens data og producere rapporterne alt sammen manuelle trin — og manuelle trin er både langsomme og stille farlige. Hver release åd engineering‑tid og bar chancen for en fejl, og det tilbagevendende data- og rapporteringsarbejde sad der og åd kapacitet uge efter uge.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Opgave.&lt;/strong&gt; At automatisere hele vejen fra kode til produktion, plus det tilbagevendende databehandlings- og rapporteringsarbejde, var opgaven — målet var releases, der var hurtige, sikre og reproducerbare frem for et omhyggeligt manuelt ritual hver gang.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Handling.&lt;/strong&gt; Hele vejen blev automatiseret. GitHub Actions‑pipelines overtog test‑build‑deploy‑cyklussen, så en release holdt op med at afhænge af, at nogen huskede trinene. Den tilbagevendende databehandling og rapporterne flyttede over i planlagte Python-, Bash- og SQL‑jobs, så de bare kørte i stedet for at være nogens pligt. Og konfigurationen og secrets blev standardiseret, så hvert miljø opførte sig ens — hvilket er det, der dræber &amp;ldquo;det virker på min maskine&amp;rdquo;-overraskelserne, for der holder op med at være en &amp;ldquo;min maskine&amp;rdquo;, der er anderledes end produktion.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Resultat.&lt;/strong&gt; Udrulning, databehandling og rapportering blev alle automatiserede og pålidelige, det manuelle slid kom af teamets bord, og releasecyklussen blev kortere. Teamet kunne rette sin opmærksomhed mod produktet i stedet for driften, der var pakket omkring det.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Har automatiseret levering af 20 GIS‑datapipelines og ETL‑processer for appdata og strømlinet infrastrukturautomatisering og rapportering.</title>
    <id>https://data.engineer.company/da/portfolio/automated-delivery-of-20-gis-data-pipelines-and-17/</id>
    <link href="https://data.engineer.company/da/portfolio/automated-delivery-of-20-gis-data-pipelines-and-17/" rel="alternate" type="text/html" />
    <updated>2026-09-13T15:01:29+02:00</updated>
    <published>2026-09-13T15:01:29+02:00</published>
    <category term="Automatisering &amp; CI/CD" scheme="https://data.engineer.company/da/categories/" />
    <category term="Data engineering" scheme="https://data.engineer.company/da/categories/" />
    <category term="Datapipelines (ETL/ELT)" scheme="https://data.engineer.company/da/categories/" />
    <category term="DevOps" scheme="https://data.engineer.company/da/categories/" />
    <category term="Drift &amp; backup" scheme="https://data.engineer.company/da/categories/" />
    <category term="GIS / Geospatial" scheme="https://data.engineer.company/da/categories/" />
    <category term="Monitorering &amp; observability" scheme="https://data.engineer.company/da/categories/" />
    <category term="DevOps &amp; CI/CD‑automatisering" scheme="https://data.engineer.company/da/services/" />
    <category term="GIS &amp; geospatiale løsninger" scheme="https://data.engineer.company/da/services/" />
    <category term="Udvikling af datapipelines (ETL/ELT)" scheme="https://data.engineer.company/da/services/" />
    <summary>Automatiserede 20 GIS-datapipelines og ETL-processer for appdata — strømlinet infrastrukturautomatisering og pålidelige, aktuelle data.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Situation.&lt;/strong&gt; Platformen kørte på en masse GIS‑datapipelines og ETL‑processer for appdata, og de blev leveret og overvåget i hånden. Håndkørte pipelines skaber flaskehalse, de driver ud af konsistens, og værst af alt bærer de en konstant lav risiko for, at en stille fejler, og ingen bemærker det, før dataene allerede er forkerte længere nede.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Opgave.&lt;/strong&gt; At automatisere leveringen af de pipelines og ETL‑processer — så dataene flød pålideligt og forudsigeligt uden nogen til at føre dem igennem — var opgaven.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Handling.&lt;/strong&gt; Tyve GIS‑datapipelines og ETL‑processerne for appdata kom under automatiseret levering, fra ende til anden. Planlægningen, loggingen og fejlhåndteringen blev standardiseret, så hver pipeline opførte sig ens og, afgørende, man kunne se, når en ikke gjorde — en stille fejl er kun stille, hvis intet holder øje. Og de blev foldet ind i den eksisterende infrastrukturautomatisering og rapportering, så de var en del af ét sammenhængende system frem for en skuffe fuld af scripts, nogen skulle huske at køre.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Resultat.&lt;/strong&gt; Alle tyve pipelines og deres ETL kørte automatisk og forudsigeligt, og hele billedet af infrastrukturautomatisering og rapportering blev pænere for det. Forretningen fik pålidelige, aktuelle data, uden at nogen skulle gå dem igennem i hånden — og uden den stille‑fejl‑risiko hængende over sig.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Har automatiseret 100 kritiske databackups ved hjælp af Barman, Google Cloud, Bash og Python og sikret dataintegritet på tværs af databaser.</title>
    <id>https://data.engineer.company/da/portfolio/automated-100-critical-data-backups-using-barman-google-18/</id>
    <link href="https://data.engineer.company/da/portfolio/automated-100-critical-data-backups-using-barman-google-18/" rel="alternate" type="text/html" />
    <updated>2026-09-13T15:01:29+02:00</updated>
    <published>2026-09-13T15:01:29+02:00</published>
    <category term="Automatisering &amp; CI/CD" scheme="https://data.engineer.company/da/categories/" />
    <category term="Cloud" scheme="https://data.engineer.company/da/categories/" />
    <category term="Databaser" scheme="https://data.engineer.company/da/categories/" />
    <category term="DevOps" scheme="https://data.engineer.company/da/categories/" />
    <category term="Drift &amp; backup" scheme="https://data.engineer.company/da/categories/" />
    <category term="Infrastruktur" scheme="https://data.engineer.company/da/categories/" />
    <category term="PostgreSQL" scheme="https://data.engineer.company/da/categories/" />
    <category term="Python" scheme="https://data.engineer.company/da/categories/" />
    <category term="Backup &amp; disaster recovery" scheme="https://data.engineer.company/da/services/" />
    <category term="Databaseadministration (DBA)" scheme="https://data.engineer.company/da/services/" />
    <category term="DevOps &amp; CI/CD‑automatisering" scheme="https://data.engineer.company/da/services/" />
    <summary>Automatiserede 100 kritiske databackups med Barman, Google Cloud, Bash og Python — datagenoprettelse gik fra antagelse til testet faktum.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Situation.&lt;/strong&gt; De kritiske GIS‑data, applikationsinstanserne og databaserne var spredt over systemer med backups, der var inkonsistente og delvist manuelle. For et produkt, der lever på sine data, er det ikke en risiko, man kan lade ligge — og den dag, man faktisk har brug for en backup, er præcis den værste dag at finde ud af, at den var ufuldstændig.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Opgave.&lt;/strong&gt; Opgaven var at garantere, at alle de kritiske data kunne gendannes, hvilket betød at automatisere omfattende, verificerede backups på tværs af hele estatet — verificerede som det ord, der betyder noget.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Handling.&lt;/strong&gt; Backup‑regimet blev bygget fra ende til anden. Hundrede kritiske databackups blev automatiseret, med Barman på PostgreSQL‑siden og Google Cloud, der holdt offsite‑kopierne, og det hele blev orkestreret og valideret med Bash og Python — for en backup, man har taget, men aldrig tjekket, er ikke rigtig en backup, det er et håb. Så der var retention‑politikker til at holde dem aktuelle og integritetstjek til at bekræfte, at hver enkelt faktisk var god, ikke bare til stede.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Resultat.&lt;/strong&gt; Backups kørte automatisk og kunne verificeres på tværs af hver database, hvilket gjorde datagenoprettelighed fra en antagelse til noget testet. En væsentlig driftsrisiko kom af forretningen og blev erstattet af en genopretningsvej, man faktisk kunne stole på — forskellen var, at denne var tjekket, ikke bare konfigureret.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Har optimeret prognose- og investeringsstrategier for 11 eldistributionsoperatører og øget driftseffektiviteten gennem datadrevne GIS‑løsninger.</title>
    <id>https://data.engineer.company/da/portfolio/optimized-forecasting-and-investment-strategies-for-11-electricity-27/</id>
    <link href="https://data.engineer.company/da/portfolio/optimized-forecasting-and-investment-strategies-for-11-electricity-27/" rel="alternate" type="text/html" />
    <updated>2026-09-13T15:01:29+02:00</updated>
    <published>2026-09-13T15:01:29+02:00</published>
    <category term="Data engineering" scheme="https://data.engineer.company/da/categories/" />
    <category term="Dataanalyse" scheme="https://data.engineer.company/da/categories/" />
    <category term="GIS / Geospatial" scheme="https://data.engineer.company/da/categories/" />
    <category term="Produkt &amp; krav" scheme="https://data.engineer.company/da/categories/" />
    <category term="Stakeholder &amp; rapportering" scheme="https://data.engineer.company/da/categories/" />
    <category term="Dataanalyse &amp; BI‑dashboards" scheme="https://data.engineer.company/da/services/" />
    <category term="GIS &amp; geospatiale løsninger" scheme="https://data.engineer.company/da/services/" />
    <category term="Produktstrategi &amp; kravspecifikation" scheme="https://data.engineer.company/da/services/" />
    <summary>Optimerede prognoser og investeringsstrategi for 11 eldistributionsoperatører med datadrevet GIS — troværdig, målrettet planlægning.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Situation.&lt;/strong&gt; Eldistributionsoperatører står og falder på beslutninger om, hvor de skal forstærke nettet, og hvor de skal placere deres penge, og elleve af dem traf de beslutninger uden meget geospatial analyse under sig. De havde driftsdataene. Det, de ikke havde, var en måde at se dem på kortet, dér hvor mønstrene faktisk lever.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Opgave.&lt;/strong&gt; Opgaven var at skærpe deres prognoser og investeringsstrategier med GIS — at gøre tabeller af aflæsninger til noget, der viste dem, hvor kapaciteten blev knap, hvor risikoen byggede sig op, og hvor den næste krone var bedst givet ud.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Handling.&lt;/strong&gt; Deres driftsdata blev bragt sammen med geospatial modellering, så de to forstærkede hinanden. I stedet for at lave prognoser i det abstrakte kunne nettet ses rumligt og stilles konkrete spørgsmål: hvilke strækninger var på vej mod deres grænser, hvilke områder retfærdiggjorde investering først. For elleve operatører betød det at tilpasse analysen til, hvordan hver af dem faktisk drev deres net, ikke at række alle den samme skabelon og håbe, den passede.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Resultat.&lt;/strong&gt; Operatørerne gik derfra med prognoser, de kunne stole på, og investeringsbeslutninger, der var målrettede frem for håbefulde. At forankre planlægningen i det, kortet viste, gjorde det hele mere effektivt — penge og opmærksomhed gik derhen, hvor dataene pegede, i stedet for derhen, hvor vanen gjorde.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Har indsamlet og analyseret forretningskrav og omsat dem til konkrete funktioner og user stories i overensstemmelse med data governance‑standarder.</title>
    <id>https://data.engineer.company/da/portfolio/gathered-and-analyzed-business-requirements-to-translate-into-31/</id>
    <link href="https://data.engineer.company/da/portfolio/gathered-and-analyzed-business-requirements-to-translate-into-31/" rel="alternate" type="text/html" />
    <updated>2026-09-13T15:01:29+02:00</updated>
    <published>2026-09-13T15:01:29+02:00</published>
    <category term="Agile &amp; Scrum" scheme="https://data.engineer.company/da/categories/" />
    <category term="Data governance" scheme="https://data.engineer.company/da/categories/" />
    <category term="Dokumentation" scheme="https://data.engineer.company/da/categories/" />
    <category term="Produkt &amp; krav" scheme="https://data.engineer.company/da/categories/" />
    <category term="Projektledelse" scheme="https://data.engineer.company/da/categories/" />
    <category term="Stakeholder &amp; rapportering" scheme="https://data.engineer.company/da/categories/" />
    <category term="Data governance &amp; datakvalitet" scheme="https://data.engineer.company/da/services/" />
    <category term="Produktstrategi &amp; kravspecifikation" scheme="https://data.engineer.company/da/services/" />
    <category term="Projektledelse (Agile)" scheme="https://data.engineer.company/da/services/" />
    <summary>Omsatte forretningskrav til klare funktioner og user stories efter data governance-standarder — mindre tvetydighed og omarbejde.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Situation.&lt;/strong&gt; Krav plejede at ankomme som samtaler — nogen ville have noget, sådan cirka, og det faldt tilbage på udviklerne at gætte på kanterne. At gætte betyder omarbejde, og omarbejde er omtrent den dyreste måde, der findes, at bygge noget på.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Opgave.&lt;/strong&gt; Rollen sad mellem forretningen og engineeringen og oversatte den ene til den anden: at gøre løse behov til arbejde, en udvikler kunne tage fat på uden at gætte, og at holde det i tråd med data governance‑standarderne undervejs.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Handling.&lt;/strong&gt; Kravene blev arbejdet ud med interessenterne direkte, med de akavede spørgsmål stillet tidligt i stedet for opdaget sent, og skrevet op som funktioner og user stories, der faktisk sagde, hvad &amp;ldquo;færdig&amp;rdquo; betød. Hver enkelt blev holdt op mod governance‑reglerne, for en funktion, der er nyttig, men håndterer data forkert, er ikke rigtig færdig. Hele formålet var, at nogen kunne læse en story og bygge det rigtige første gang.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Resultat.&lt;/strong&gt; Udviklingen kørte ud fra klare, aftalte funktioner i stedet for halvt forståede ønsker. Tvetydigheden faldt, og omarbejdet faldt med den, og leveringen forblev rettet mod de faktiske forretningsmål — inden for data governance‑linjerne frem for pyntet til at passe bagefter.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Har ledet udvikling, idriftsættelse og support af over 30 GIS‑projekter og udvist ekspertise i PostgreSQL, Bash, Python, JavaScript, GDAL, ArcGIS, PostGIS og Mapbox.</title>
    <id>https://data.engineer.company/da/portfolio/led-the-development-deployment-and-support-of-over-35/</id>
    <link href="https://data.engineer.company/da/portfolio/led-the-development-deployment-and-support-of-over-35/" rel="alternate" type="text/html" />
    <updated>2026-09-13T15:01:29+02:00</updated>
    <published>2026-09-13T15:01:29+02:00</published>
    <category term="Backend‑udvikling" scheme="https://data.engineer.company/da/categories/" />
    <category term="Data engineering" scheme="https://data.engineer.company/da/categories/" />
    <category term="Databaser" scheme="https://data.engineer.company/da/categories/" />
    <category term="Drift &amp; backup" scheme="https://data.engineer.company/da/categories/" />
    <category term="Full stack‑udvikling" scheme="https://data.engineer.company/da/categories/" />
    <category term="GIS / Geospatial" scheme="https://data.engineer.company/da/categories/" />
    <category term="PostgreSQL" scheme="https://data.engineer.company/da/categories/" />
    <category term="Python" scheme="https://data.engineer.company/da/categories/" />
    <category term="SQL" scheme="https://data.engineer.company/da/categories/" />
    <category term="Teamledelse" scheme="https://data.engineer.company/da/categories/" />
    <category term="Teknisk ledelse" scheme="https://data.engineer.company/da/categories/" />
    <category term="Webudvikling" scheme="https://data.engineer.company/da/categories/" />
    <category term="Backend- &amp; API‑udvikling" scheme="https://data.engineer.company/da/services/" />
    <category term="Full stack‑produktudvikling" scheme="https://data.engineer.company/da/services/" />
    <category term="GIS &amp; geospatiale løsninger" scheme="https://data.engineer.company/da/services/" />
    <category term="Teknisk ledelse &amp; rådgivning" scheme="https://data.engineer.company/da/services/" />
    <category term="Udvikling af datapipelines (ETL/ELT)" scheme="https://data.engineer.company/da/services/" />
    <summary>Ledede udvikling, drift og support af 30+ GIS-projekter med PostgreSQL, Python, GDAL, ArcGIS, PostGIS og Mapbox — hele livscyklussen.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Situation.&lt;/strong&gt; Virksomhedens hele output var made‑to‑measure GIS — skræddersyet kortlægning og geodata‑systemer bygget til en kundes konkrete problem og så holdt kørende, når de var live. At bygge tingen er kun halvdelen; et geospatialt projekt, der ryger ud og så vælter i produktion, er ikke rigtig blevet leveret.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Opgave.&lt;/strong&gt; De projekter kørte fra ende til anden gennem den her rolle — udviklingen, udrulningen og supporten, når de først var live — med den tekniske retning på tværs af en ret bred stak.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Handling.&lt;/strong&gt; Leveringen kørte på mere end tredive GIS‑projekter, hands‑on på tværs af stakken hele vejen. PostgreSQL med PostGIS under til geodataene, GDAL/OGR til at flytte dem mellem formater — shapefiles, GeoJSON, GeoTIFF, KML, vector tiles — og QGIS og JOSM til selve dataarbejdet. Foran på det webkort bygget på Mapbox GL og Leaflet, nogle gange mod ArcGIS- eller HERE‑API&amp;rsquo;erne, med app‑laget i JavaScript, Python, PHP og SQL. Arbejdet spændte fra 2D- og 3D‑digital kortlægning over LiDAR‑behandling, georektifikation og vektorisering til indendørs kortlægning og navigation. Og ansvaret rakte forbi det punkt, tingen var sendt af sted — udrulningen og den løbende support i produktion var også en del af det, så problemer blev ikke givet videre; beslutningerne skulle leves med.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Resultat.&lt;/strong&gt; Tredive‑plus projekter bygget, udrullet og supporteret på tværs af hele det spænd. At stå på krogen for hele livscyklussen frem for bare bygget er det, der holdt kvaliteten ærlig — man designer anderledes, når man ved, det er en selv, der får opkaldet, hvis det går i stykker.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Har strømlinet processer for dataanalyse og softwareudvikling og sparet 4.000 timer ved at indføre CI/CD‑praksis med GitHub, GitLab, Bash og Python.</title>
    <id>https://data.engineer.company/da/portfolio/streamlined-data-analysis-and-software-development-processes-saving-43/</id>
    <link href="https://data.engineer.company/da/portfolio/streamlined-data-analysis-and-software-development-processes-saving-43/" rel="alternate" type="text/html" />
    <updated>2026-09-13T15:01:29+02:00</updated>
    <published>2026-09-13T15:01:29+02:00</published>
    <category term="Automatisering &amp; CI/CD" scheme="https://data.engineer.company/da/categories/" />
    <category term="Data engineering" scheme="https://data.engineer.company/da/categories/" />
    <category term="Datapipelines (ETL/ELT)" scheme="https://data.engineer.company/da/categories/" />
    <category term="Dataanalyse" scheme="https://data.engineer.company/da/categories/" />
    <category term="DevOps" scheme="https://data.engineer.company/da/categories/" />
    <category term="Python" scheme="https://data.engineer.company/da/categories/" />
    <category term="Dataanalyse &amp; BI‑dashboards" scheme="https://data.engineer.company/da/services/" />
    <category term="DevOps &amp; CI/CD‑automatisering" scheme="https://data.engineer.company/da/services/" />
    <category term="Udvikling af datapipelines (ETL/ELT)" scheme="https://data.engineer.company/da/services/" />
    <summary>Sparede ~4.000 timer ved at indføre CI/CD med GitHub, GitLab, Bash og Python — hurtigere dataanalyse og udvikling, mere konsistent.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Situation.&lt;/strong&gt; Både dataanalysearbejdet og softwareudviklingen blev holdt tilbage af det samme: manuelle processer. Arbejde bevægede sig fra udvikling til levering på en langsom, inkonsistent måde, og analysesiden havde sin egen bunke gentagne trin, som nogen lavede i hånden hver gang.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Opgave.&lt;/strong&gt; Målet var at strømline begge dele ved at bringe moderne automatisering og CI/CD‑praksis til workflows, der ikke havde haft dem.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Handling.&lt;/strong&gt; CI/CD‑praksis blev indført, bygget på GitHub og GitLab, med Bash og Python, der lavede automatiseringsarbejdet nedenunder. De gentagne trin på tværs af både dataanalyse- og udviklingsworkflows blev automatiseret, og hvordan arbejdet bevægede sig fra udvikling og hele vejen til levering blev standardiseret, så det var det samme hver gang frem for genopfundet pr. projekt. At bringe analysesiden ind i den samme disciplinerede pipeline som udviklingsarbejdet var en stor del af det — den var blevet behandlet som en separat, mere manuel verden.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Resultat.&lt;/strong&gt; De strømlinede processer sparede omkring 4.000 timer og satte fart på både dataanalysen og softwareudviklingen, og lige så nyttigt gjorde de det, der blev sendt ud, mere konsistent — færre overraskelser fra arbejde, der var blevet gjort en anelse forskelligt hver gang.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Har udviklet et rapporteringssystem til dataanalyse og øget den kvartalsvise softwareomsætning med 400 % gennem Python‑baserede PDF‑rapporter.</title>
    <id>https://data.engineer.company/da/portfolio/developed-a-data-analytics-reporting-system-increasing-quarterly-44/</id>
    <link href="https://data.engineer.company/da/portfolio/developed-a-data-analytics-reporting-system-increasing-quarterly-44/" rel="alternate" type="text/html" />
    <updated>2026-09-13T15:01:29+02:00</updated>
    <published>2026-09-13T15:01:29+02:00</published>
    <category term="Automatisering &amp; CI/CD" scheme="https://data.engineer.company/da/categories/" />
    <category term="Backend‑udvikling" scheme="https://data.engineer.company/da/categories/" />
    <category term="Data engineering" scheme="https://data.engineer.company/da/categories/" />
    <category term="Dataanalyse" scheme="https://data.engineer.company/da/categories/" />
    <category term="Produkt &amp; krav" scheme="https://data.engineer.company/da/categories/" />
    <category term="Python" scheme="https://data.engineer.company/da/categories/" />
    <category term="Stakeholder &amp; rapportering" scheme="https://data.engineer.company/da/categories/" />
    <category term="Backend- &amp; API‑udvikling" scheme="https://data.engineer.company/da/services/" />
    <category term="Dataanalyse &amp; BI‑dashboards" scheme="https://data.engineer.company/da/services/" />
    <category term="Produktstrategi &amp; kravspecifikation" scheme="https://data.engineer.company/da/services/" />
    <summary>Byggede et Python-rapporteringssystem til dataanalyse, der øgede den kvartalsvise softwareomsætning 400 % med klare, rettidige rapporter.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Situation.&lt;/strong&gt; Interessenterne fik ikke analyse i nogen rettidig, læsbar form. Dataene fandtes, men at omsætte dem til noget, man faktisk kunne træffe en beslutning ud fra, var langsomt og manuelt, så indblikket i, hvordan tingene præsterede, haltede, og de kommercielle beslutninger haltede med.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Opgave.&lt;/strong&gt; At bygge et rapporteringssystem til dataanalyse — et, der omsatte rådata til klar, regelmæssig indsigt uden at nogen håndsamlede det hver gang — var jobbet.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Handling.&lt;/strong&gt; Et rapporteringssystem genererede PDF‑rapporter i Python og automatiserede hele kæden: at trække dataene, køre analysen og præsentere det i et rent, konsistent format, interessenterne faktisk kunne læse. Pointen var regelmæssighed og klarhed — den samme professionelle rapport landede forudsigeligt, så tallene blev noget, folk kiggede på som en selvfølge frem for noget, de skulle gå ud og grave frem.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Resultat.&lt;/strong&gt; Den rapportering er det, der drev den kvartalsvise softwareomsætning op med 400 %. At gøre analysen bedre og hurtigere var ikke en back‑office‑finesse — sæt klare, rettidige tal foran de folk, der træffer kommercielle beslutninger, og beslutningerne bliver bedre, og her viste det sig direkte på omsætningen.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Har automatiseret databehandlingsopgaver med shell‑scripting, PL/pgSQL, Python og Transact‑SQL og øget produktiviteten og effektiviteten.</title>
    <id>https://data.engineer.company/da/portfolio/automated-data-processing-tasks-using-shell-scripting-pl-45/</id>
    <link href="https://data.engineer.company/da/portfolio/automated-data-processing-tasks-using-shell-scripting-pl-45/" rel="alternate" type="text/html" />
    <updated>2026-09-13T15:01:29+02:00</updated>
    <published>2026-09-13T15:01:29+02:00</published>
    <category term="Automatisering &amp; CI/CD" scheme="https://data.engineer.company/da/categories/" />
    <category term="Data engineering" scheme="https://data.engineer.company/da/categories/" />
    <category term="Databaser" scheme="https://data.engineer.company/da/categories/" />
    <category term="Datapipelines (ETL/ELT)" scheme="https://data.engineer.company/da/categories/" />
    <category term="PostgreSQL" scheme="https://data.engineer.company/da/categories/" />
    <category term="Python" scheme="https://data.engineer.company/da/categories/" />
    <category term="SQL" scheme="https://data.engineer.company/da/categories/" />
    <category term="Databaseadministration (DBA)" scheme="https://data.engineer.company/da/services/" />
    <category term="DevOps &amp; CI/CD‑automatisering" scheme="https://data.engineer.company/da/services/" />
    <category term="Udvikling af datapipelines (ETL/ELT)" scheme="https://data.engineer.company/da/services/" />
    <summary>Automatiserede databehandling med Shell, PL/pgSQL, Python og Transact-SQL — højere produktivitet og slut med små, tilbagevendende fejl.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Situation.&lt;/strong&gt; Der var en stabil mængde tilbagevendende databehandlingsarbejde, der blev lavet i hånden. Manuelt dataarbejde har to problemer på én gang: det æder tid, og det er inkonsistent — lav den samme opgave i hånden nok gange, og den bliver gjort en anelse forskelligt, og nogle af de forskelle er fejl.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Opgave.&lt;/strong&gt; Målet var at automatisere de opgaver, både for at få tiden tilbage og for at gøre dem pålidelige.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Handling.&lt;/strong&gt; Databehandlingsarbejdet blev automatiseret på tværs af de databaser og systemer, det rørte, med hvad end der passede til jobbet — shell‑scripting til limen, PL/pgSQL og Transact‑SQL nede i databaserne, Python, hvor det krævede mere, end SQL kunne give. Manuelle trin blev erstattet med jobs, der kørte på samme måde hver gang, hvilket er hele pointen: et script bliver ikke træt, springer ikke et trin over og gør det ikke anderledes en fredag eftermiddag.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Resultat.&lt;/strong&gt; Produktiviteten og effektiviteten gik begge op, det manuelle arbejde kom af folks bord, og databehandlingen blev konsistent og pålidelig i stedet for en kilde til små, tilbagevendende fejl.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Har udviklet 600 PL/pgSQL‑baserede ETL/ELT‑pipelines for at strømline komplekse databehandlingsworkflows på tværs af flere PostgreSQL‑udviklings- og produktionsmiljøer.</title>
    <id>https://data.engineer.company/da/portfolio/engineered-600-pl-pgsql-based-etl-elt-pipelines-54/</id>
    <link href="https://data.engineer.company/da/portfolio/engineered-600-pl-pgsql-based-etl-elt-pipelines-54/" rel="alternate" type="text/html" />
    <updated>2026-09-13T15:01:29+02:00</updated>
    <published>2026-09-13T15:01:29+02:00</published>
    <category term="Automatisering &amp; CI/CD" scheme="https://data.engineer.company/da/categories/" />
    <category term="Data engineering" scheme="https://data.engineer.company/da/categories/" />
    <category term="Data governance" scheme="https://data.engineer.company/da/categories/" />
    <category term="Databaser" scheme="https://data.engineer.company/da/categories/" />
    <category term="Datapipelines (ETL/ELT)" scheme="https://data.engineer.company/da/categories/" />
    <category term="Performanceoptimering" scheme="https://data.engineer.company/da/categories/" />
    <category term="PostgreSQL" scheme="https://data.engineer.company/da/categories/" />
    <category term="SQL" scheme="https://data.engineer.company/da/categories/" />
    <category term="Data governance &amp; datakvalitet" scheme="https://data.engineer.company/da/services/" />
    <category term="Databaseadministration (DBA)" scheme="https://data.engineer.company/da/services/" />
    <category term="Udvikling af datapipelines (ETL/ELT)" scheme="https://data.engineer.company/da/services/" />
    <summary>Udviklede 600 PL/pgSQL ETL/ELT-pipelines på tværs af PostgreSQL dev og prod — 35 % kortere udførelsestid og 50 %+ mere gennemløb.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Situation.&lt;/strong&gt; Organisationen håndterede store mængder transaktions- og analysedata på tværs af flere PostgreSQL‑udviklings- og produktionsmiljøer. De eksisterende datapipelines var fragmenterede, manglede konsistens og forårsagede ydeevneflaskehalse, hvilket førte til forsinkelser i forretningskritisk rapportering og beslutningstagning.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Opgave.&lt;/strong&gt; Opgaven var at designe og implementere robuste, skalerbare og effektive ETL/ELT‑pipelines med PL/pgSQL for at strømline komplekse workflows til dataindtagelse, -transformation og -indlæsning. Et nøglemål var at forbedre forespørgselsydeevnen og sikre dataintegritet på tværs af alle miljøer.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Handling.&lt;/strong&gt; Over 600 PL/pgSQL‑baserede ETL/ELT‑pipelines blev udviklet til at automatisere udtræk, transformation og indlæsning af data fra forskellige kilder. Partitionerede tabeller og materialized views blev udnyttet for at optimere læseydeevnen, primary- og foreign key‑constraints anvendt for at bevare referentiel integritet, unikke og composite‑indeks designet for at fremskynde JOIN‑operationer, exception handling og transaktionskontrol indbygget for fejltolerance samt inkrementelle loads aktiveret via change data capture (CDC) og timestamp‑baserede deltaer, hvilket reducerede behandlingstiden med over 60 %. Automatiserede logging- og revisionsprocedurer blev også udviklet.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Resultat.&lt;/strong&gt; Den nye ETL/ELT‑ramme forbedrede markant konsistensen, pålideligheden og ydeevnen af databehandlingsworkflows: en 35 % reduktion i den gennemsnitlige pipeline‑udførelsestid, over 50 % øget gennemløb med næsten realtids‑datatilgængelighed, over 90 % færre transformationsfejl gennem bedre constraint‑håndhævelse og validering samt forbedret vedligeholdelighed og skalerbarhed med minimal omarbejde ved fremtidige datamodelændringer.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Arkitekt, udviklet, implementeret, understøttet infrastruktur, databehandling og kortapplikationen i 2 år uden pause, uden weekender, helligdage eller ferie, 10–14 timer om dagen.</title>
    <id>https://data.engineer.company/da/portfolio/architected-developed-implemented-supported-infrastructure-data-processing-and-55/</id>
    <link href="https://data.engineer.company/da/portfolio/architected-developed-implemented-supported-infrastructure-data-processing-and-55/" rel="alternate" type="text/html" />
    <updated>2026-09-13T15:01:29+02:00</updated>
    <published>2026-09-13T15:01:29+02:00</published>
    <category term="Data engineering" scheme="https://data.engineer.company/da/categories/" />
    <category term="Datapipelines (ETL/ELT)" scheme="https://data.engineer.company/da/categories/" />
    <category term="Drift &amp; backup" scheme="https://data.engineer.company/da/categories/" />
    <category term="Full stack‑udvikling" scheme="https://data.engineer.company/da/categories/" />
    <category term="GIS / Geospatial" scheme="https://data.engineer.company/da/categories/" />
    <category term="Infrastruktur" scheme="https://data.engineer.company/da/categories/" />
    <category term="Platformarkitektur" scheme="https://data.engineer.company/da/categories/" />
    <category term="Full stack‑produktudvikling" scheme="https://data.engineer.company/da/services/" />
    <category term="GIS &amp; geospatiale løsninger" scheme="https://data.engineer.company/da/services/" />
    <category term="Platform- &amp; løsningsarkitektur" scheme="https://data.engineer.company/da/services/" />
    <category term="Site reliability &amp; monitorering" scheme="https://data.engineer.company/da/services/" />
    <category term="Udvikling af datapipelines (ETL/ELT)" scheme="https://data.engineer.company/da/services/" />
    <summary>Arkitekterede, byggede og driftede infrastruktur, databehandling og kortapp i to år uden pause — produktets pålidelige rygrad.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Situation.&lt;/strong&gt; En green energy‑startup i en tidlig fase var afhængig af én platform til at spore, overvåge og optimere vedvarende energiaktiver, men havde hverken et dedikeret infrastrukturteam eller en etableret ingeniørorganisation til at bygge og drive den. Hele det tekniske fundament — cloud‑infrastruktur, datapipelines og den kundevendte GIS‑kortapplikation — skulle skabes og holdes kørende uafbrudt, på et marked hvor enhver nedetid eller datamangel direkte svækkede kundernes tillid og omsætningen.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Opgave.&lt;/strong&gt; Opgaven var egenhændigt at arkitektere, bygge og drive hele systemet fra ende til anden — på tværs af platform- og dataingeniørarbejde, DevOps og site reliability. Ud over at skrive softwaren betød det at eje produktionsmiljøet: at provisionere og hærde infrastruktur, designe databehandlingslaget der fodrede kortet, og garantere at applikationen forblev tilgængelig døgnet rundt for en voksende kundebase — alt sammen inden for en hurtig startups rammer og ubønhørlige tempo.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Handling.&lt;/strong&gt; I to år blev infrastrukturen, datapipelines og kortapplikationen designet, implementeret og understøttet uden afbrydelse — uden weekender, helligdage eller ferie, ofte ti til fjorten timer om dagen. En pragmatisk, modulær arkitektur blev valgt for at holde en enmandsdrift vedligeholdelsesvenlig, med automatiseret provisionering, monitorering og alarmering, så problemer kunne opdages og løses hurtigt. Databehandlingen blev løbende optimeret for pålidelighed og ydeevne, releases blev udrullet trinvist, og hvert lag — fra servere til det brugervendte kort — blev personligt vedligeholdt og forbedret ud fra reel kundeanvendelse.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Resultat.&lt;/strong&gt; Platformen forblev konstant tilgængelig og udviklede sig fra en skrøbelig tidlig prototype til produktets pålidelige rygrad og bar virksomheden gennem dens kritiske vækstfase alene på styrken af én ingeniørs ejerskab. Denne praktiske forvaltning holdt infrastruktur, data og kortapplikation pålidelig nok til at understøtte mersalg, datalicensering og tiltrækning af nye kunder og demonstrerede en sjælden grad af engagement, bredde og ansvar fra ende til anden på tværs af hele stakken.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Har arkitekteret en lagdelt maritim platform, der adskiller en Next.js PWA‑frontend, et Go (Huma/Fiber) API og et PostgreSQL‑funktionslag og holder al forretningslogik i databasen.</title>
    <id>https://data.engineer.company/da/portfolio/architected-a-layered-maritime-platform-separating-a-next-57/</id>
    <link href="https://data.engineer.company/da/portfolio/architected-a-layered-maritime-platform-separating-a-next-57/" rel="alternate" type="text/html" />
    <updated>2026-09-13T15:01:29+02:00</updated>
    <published>2026-09-13T15:01:29+02:00</published>
    <category term="API&#39;er &amp; integration" scheme="https://data.engineer.company/da/categories/" />
    <category term="Backend‑udvikling" scheme="https://data.engineer.company/da/categories/" />
    <category term="Databaser" scheme="https://data.engineer.company/da/categories/" />
    <category term="Frontend‑udvikling" scheme="https://data.engineer.company/da/categories/" />
    <category term="Full stack‑udvikling" scheme="https://data.engineer.company/da/categories/" />
    <category term="Løsningsarkitektur" scheme="https://data.engineer.company/da/categories/" />
    <category term="Platformarkitektur" scheme="https://data.engineer.company/da/categories/" />
    <category term="PostgreSQL" scheme="https://data.engineer.company/da/categories/" />
    <category term="Teknisk ledelse" scheme="https://data.engineer.company/da/categories/" />
    <category term="Backend- &amp; API‑udvikling" scheme="https://data.engineer.company/da/services/" />
    <category term="Databasedesign &amp; datamodellering" scheme="https://data.engineer.company/da/services/" />
    <category term="Frontend‑udvikling" scheme="https://data.engineer.company/da/services/" />
    <category term="Full stack‑produktudvikling" scheme="https://data.engineer.company/da/services/" />
    <category term="Platform- &amp; løsningsarkitektur" scheme="https://data.engineer.company/da/services/" />
    <summary>Arkitekterede en lagdelt maritim platform — Next.js PWA, et Go (Huma/Fiber) API og et PostgreSQL-funktionslag med al forretningslogik.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Situation.&lt;/strong&gt; NextMariner skulle være en maritim platform — professionelt netværk, virksomhedsanmeldelser, sponsoreret uddannelse — og det var et ungt produkt, hvilket er en pæn måde at sige, at kravene ville flytte sig en hel del. Det, der skulle undgås, var en arkitektur, hvor en ændret forretningsregel betød, at man skulle røre frontenden, API&amp;rsquo;et og databasen på én gang. På en lille kodebase, der vokser hurtigt, er det den slags kobling, der gør en to‑linjers ændring til en hel eftermiddag.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Opgave.&lt;/strong&gt; Som arkitekt var beslutningen på forhånd, hvor hver slags logik boede, med grænser tydelige nok til at holde under pres, i stedet for at blive udvisket første gang nogen havde travlt.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Handling.&lt;/strong&gt; Det landede på tre lag, ét job hver. Next.js‑frontenden står for præsentation og interaktivitet og intet andet. Go‑API&amp;rsquo;et — Huma oven på Fiber — er bevidst tyndt: det router, validerer requesten, laver sikkerhedsfiltreringen og orkestrerer, men det rummer slet ingen forretningslogik. Forretningslogikken bor i PostgreSQL‑funktioner, som samler det fulde resultat og giver det tilbage, som API&amp;rsquo;et videresender. Så når en regel ændrer sig, ændrer den sig i ét lag, i SQL, og de to andre behøver ikke vide det. Grænserne blev skrevet ned og håndhævet i review, for en konvention, ingen holder øje med, holder op med at være en.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Resultat.&lt;/strong&gt; Tingen forblev nem at holde i hovedet. Forretningslogikken sidder ét sted, man faktisk kan revidere, API&amp;rsquo;et er en kedelig adapter på den gode måde, og frontenden er ligeglad, når skemaet flytter sig under den. Den adskillelse er det, der lod produktet blive ved med at skrue funktioner på, uden at arkitekturen stille og roligt rådnede.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Har designet en JSON passthrough‑arkitektur, hvor PostgreSQL‑funktioner returnerer komplet JSON, som Go‑API&#39;et videresender uændret, hvilket eliminerer mellemliggende unmarshalling og afkobler frontenden fra skemaændringer.</title>
    <id>https://data.engineer.company/da/portfolio/designed-a-json-passthrough-architecture-where-postgresql-functions-58/</id>
    <link href="https://data.engineer.company/da/portfolio/designed-a-json-passthrough-architecture-where-postgresql-functions-58/" rel="alternate" type="text/html" />
    <updated>2026-09-13T15:01:29+02:00</updated>
    <published>2026-09-13T15:01:29+02:00</published>
    <category term="API&#39;er &amp; integration" scheme="https://data.engineer.company/da/categories/" />
    <category term="Backend‑udvikling" scheme="https://data.engineer.company/da/categories/" />
    <category term="Databaser" scheme="https://data.engineer.company/da/categories/" />
    <category term="Performanceoptimering" scheme="https://data.engineer.company/da/categories/" />
    <category term="Platformarkitektur" scheme="https://data.engineer.company/da/categories/" />
    <category term="PostgreSQL" scheme="https://data.engineer.company/da/categories/" />
    <category term="SQL" scheme="https://data.engineer.company/da/categories/" />
    <category term="Backend- &amp; API‑udvikling" scheme="https://data.engineer.company/da/services/" />
    <category term="Databasedesign &amp; datamodellering" scheme="https://data.engineer.company/da/services/" />
    <category term="Platform- &amp; løsningsarkitektur" scheme="https://data.engineer.company/da/services/" />
    <summary>Designede en JSON passthrough, hvor PostgreSQL-funktioner returnerer komplet JSON videresendt uændret af Go-API&#39;et — frontend afkoblet fra skema.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Situation.&lt;/strong&gt; Den sædvanlige måde, data kommer fra en database til en browser, er et stafetløb af transformationer. Databasen giver API&amp;rsquo;et rækker, API&amp;rsquo;et unmarshaller dem til structs, omformer dem, serialiserer dem tilbage til JSON, og først da ryger de ud. Hvert af de spring er kode, man skriver, kode, man tester, og endnu et sted, hvor API&amp;rsquo;ets idé om dataene og databasens idé om dem kan glide fra hinanden.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Opgave.&lt;/strong&gt; Idéen var at springe stafetløbet over. Hvis databasen kunne returnere det færdige svar, kunne API&amp;rsquo;et bare sende det videre, og frontenden kunne afhænge direkte af databasens form i stedet for af en håndholdt kopi af den, der lå i Go.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Handling.&lt;/strong&gt; Så det blev bygget som en ren passthrough. PostgreSQL‑funktionerne samler hele svaret som JSON — formningen er en SQL‑opgave, gjort der, hvor dataene i forvejen er. Go‑handleren tager det tilbage som json.RawMessage og videresender det uændret; den dekomponerer det aldrig, re‑encoder det aldrig. En lille QueryJSON‑helper gjorde det mønster til vejen med mindst modstand frem for noget, man skulle huske at gøre. Det, der faldt fra, var alt det mellemliggende maskineri, et konventionelt lagdelt API samler op — DTO&amp;rsquo;erne, mapperne, svar‑structene.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Resultat.&lt;/strong&gt; Handler‑koden blev dramatisk kortere, og vigtigere endnu holdt frontenden op med at være koblet til Go. Skift, hvad en funktion returnerer, og den nye form flyder direkte igennem til klienten, uden at nogen redigerer en linje handler‑kode. Færre bevægelige dele, og en hel kategori af drift mellem lag findes simpelthen ikke her.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Har designet et function‑first datalag i PostgreSQL — 1.275 stored functions på tværs af 34 skemaer — så hver læsning og skrivning går gennem en funktion, databasen kan tildele rettigheder til, frem for gennem en tabel.</title>
    <id>https://data.engineer.company/da/portfolio/designed-a-postgresql-function-first-data-layer-across-63/</id>
    <link href="https://data.engineer.company/da/portfolio/designed-a-postgresql-function-first-data-layer-across-63/" rel="alternate" type="text/html" />
    <updated>2026-09-13T15:01:29+02:00</updated>
    <published>2026-09-13T15:01:29+02:00</published>
    <category term="Backend‑udvikling" scheme="https://data.engineer.company/da/categories/" />
    <category term="Data governance" scheme="https://data.engineer.company/da/categories/" />
    <category term="Databaser" scheme="https://data.engineer.company/da/categories/" />
    <category term="Platformarkitektur" scheme="https://data.engineer.company/da/categories/" />
    <category term="PostgreSQL" scheme="https://data.engineer.company/da/categories/" />
    <category term="Sikkerhed" scheme="https://data.engineer.company/da/categories/" />
    <category term="SQL" scheme="https://data.engineer.company/da/categories/" />
    <category term="Backend- &amp; API‑udvikling" scheme="https://data.engineer.company/da/services/" />
    <category term="Data governance &amp; datakvalitet" scheme="https://data.engineer.company/da/services/" />
    <category term="Databasedesign &amp; datamodellering" scheme="https://data.engineer.company/da/services/" />
    <category term="Platform- &amp; løsningsarkitektur" scheme="https://data.engineer.company/da/services/" />
    <summary>Designede et function-first datalag i PostgreSQL — 1.275 stored functions på tværs af 34 skemaer — med adgangsgrænsen håndhævet af databasen selv.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Situation.&lt;/strong&gt; Forretningslogik har det med at lække. Lidt ender i API&amp;rsquo;et, lidt i noget SQL, en handler kører inline, og før længe er den samme regel skrevet på to‑tre lidt forskellige måder, og der er ingen steder, man kan pege hen og sige &amp;ldquo;det her er, hvad systemet gør med sine data.&amp;rdquo; Det er sådan, fejl og sikkerhedshuller kommer ind.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Opgave.&lt;/strong&gt; Målet var ét hjem til det hele: hver læsning og skrivning gennem databasen, API&amp;rsquo;et en tynd adapter, der ikke kender forretningsreglerne, og det hele muligt at låse ned til.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Handling.&lt;/strong&gt; Datalaget er function‑first. Skemaet er delt op efter domæne — identity, organization, review, message, notification og 29 mere, 34 i alt — og hver operation, appen kan udføre, er én af 1.275 PostgreSQL‑funktioner, den kalder; der er slet ingen direkte tabeladgang fra Go. Så håndhæver databasen det. Den rolle, API&amp;rsquo;et logger ind som, mariner, har EXECUTE på app‑funktionerne og USAGE på skemaerne og intet andet — ingen SELECT, ingen INSERT, ingen måde at røre en tabel direkte — hvilket løber op i cirka 4.000 eksplicitte grants frem for én generel. Funktionerne kører SECURITY DEFINER, ejet af en separat non‑login function_owner‑rolle med en pinned search_path, og superuser‑kontoen holdes reserveret til migrationer og cron, langt væk fra den kørende app.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Resultat.&lt;/strong&gt; Logikken bor ét sted, man faktisk kan revidere, API&amp;rsquo;et forbliver tyndt og kedeligt på den gode måde, og adgangsgrænsen håndhæves af Postgres selv frem for af, at alle husker reglerne. Hvis API&amp;rsquo;et på en eller anden måde blev kompromitteret, kunne det stadig ikke gøre noget, funktionerne ikke tillader. Ved 1.275 funktioner koster disciplinen noget reelt — et nyt felt er en migration og en funktionsændring, ikke en linje i en forespørgsel — og den friktion er prisen for, at grænsen holder.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Har indført tidsordnede UUID v7‑identifikatorer (PostgreSQL 18) som entitetsnøgler for at reducere fragmentering af B‑tree‑indeks og øge forespørgselshastigheden.</title>
    <id>https://data.engineer.company/da/portfolio/adopted-uuid-v7-time-ordered-identifiers-postgresql-18-64/</id>
    <link href="https://data.engineer.company/da/portfolio/adopted-uuid-v7-time-ordered-identifiers-postgresql-18-64/" rel="alternate" type="text/html" />
    <updated>2026-09-13T15:01:29+02:00</updated>
    <published>2026-09-13T15:01:29+02:00</published>
    <category term="Backend‑udvikling" scheme="https://data.engineer.company/da/categories/" />
    <category term="Data engineering" scheme="https://data.engineer.company/da/categories/" />
    <category term="Databaser" scheme="https://data.engineer.company/da/categories/" />
    <category term="Performanceoptimering" scheme="https://data.engineer.company/da/categories/" />
    <category term="PostgreSQL" scheme="https://data.engineer.company/da/categories/" />
    <category term="Databasedesign &amp; datamodellering" scheme="https://data.engineer.company/da/services/" />
    <category term="Databaseoptimering" scheme="https://data.engineer.company/da/services/" />
    <summary>Indførte tidsordnede UUID v7-nøgler (PostgreSQL 18) — mindre B-tree-fragmentering og hurtigere inserts og range-forespørgsler.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Situation.&lt;/strong&gt; Hver entitet har brug for et unikt id, og reflekvalget er en tilfældig UUID. Problemet er, at tilfældige id&amp;rsquo;er lander over det hele i et B‑tree‑indeks. Inserts spreder sig, indekset fragmenterer, og efterhånden som tabeller vokser, betaler både skrivninger og range‑scans for det. På en platform, der er ment til at blive ved med at vokse, er det en langsom lækage, man helst ikke vil bygge ind.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Opgave.&lt;/strong&gt; Bevare en UUID&amp;rsquo;s globale unikhed, men slippe af med den fragmentering, tilfældigheden fører med sig.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Handling.&lt;/strong&gt; Standarden blev UUID v7, som er tidsordnet — de førende bits er et tidsstempel, så nye rækker sorterer ind i indekset i stedet for at drysse det til. PostgreSQL 18 har det nativt som uuidv7(), pakket ind i en lille uuid_generate_v7()-funktion, så det samme kald opfører sig rent på Azures Flexible Server, og gjort til default for entiteters primærnøgler på tværs af skemaet. Intet eksotisk ved det; det er den slags beslutning, der er billig, hvis man træffer den tidligt, og en plage at eftermontere senere.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Resultat.&lt;/strong&gt; Id&amp;rsquo;er forblev globalt unikke, indekset holdt op med at fragmentere, som tilfældige UUID&amp;rsquo;er får det til, og tidsordnede inserts og range‑forespørgsler blev hurtigere — jævnt, på tværs af hver tabel, uden at nogen skulle tænke over det igen. Som en bonus ender hver entitet med en nøgle, man kan sortere efter tid gratis.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Har implementeret en katalogdrevet deep‑merge for lagrede JSON‑præferencer, hvilket forhindrer nedbrud på grund af manglende nøgler, når skemaet udvikler sig.</title>
    <id>https://data.engineer.company/da/portfolio/implemented-a-catalogue-driven-deep-merge-for-stored-65/</id>
    <link href="https://data.engineer.company/da/portfolio/implemented-a-catalogue-driven-deep-merge-for-stored-65/" rel="alternate" type="text/html" />
    <updated>2026-09-13T15:01:29+02:00</updated>
    <published>2026-09-13T15:01:29+02:00</published>
    <category term="Backend‑udvikling" scheme="https://data.engineer.company/da/categories/" />
    <category term="Data governance" scheme="https://data.engineer.company/da/categories/" />
    <category term="Databaser" scheme="https://data.engineer.company/da/categories/" />
    <category term="Migrering &amp; modernisering" scheme="https://data.engineer.company/da/categories/" />
    <category term="PostgreSQL" scheme="https://data.engineer.company/da/categories/" />
    <category term="Backend- &amp; API‑udvikling" scheme="https://data.engineer.company/da/services/" />
    <category term="Data governance &amp; datakvalitet" scheme="https://data.engineer.company/da/services/" />
    <category term="Databasedesign &amp; datamodellering" scheme="https://data.engineer.company/da/services/" />
    <summary>Implementerede en katalogdrevet deep-merge for lagrede JSON-præferencer — forhindrer nedbrud ved manglende nøgler, når skemaet vokser.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Situation.&lt;/strong&gt; Platformen lagrer JSON‑præferencer — notifikationsindstillinger og den slags — som en brugers gemte værdier lagt over et sæt defaults. Den oprindelige merge gjorde det på ét niveau. Problemet dukker op senere: tilføj en ny nøgle til defaults, og rækker gemt før den nøgle eksisterede, har den simpelthen ikke. Så læser noget klientkode det felt, får undefined og vælter — for præcis de brugere, der har været der længst.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Opgave.&lt;/strong&gt; Det skulle være sikkert at udvikle præference‑skemaet, så det at tilføje en indstilling aldrig kunne bryde de folk, der meldte sig til, før den fandtes.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Handling.&lt;/strong&gt; Enkelt‑niveau‑mergen blev erstattet med en deep‑merge drevet af defaults som et katalog. Defaults behandles som den autoritative liste over hver nøgle, der bør findes; brugerens gemte værdier merges rekursivt ovenpå, så alt i kataloget garanteret kommer ud til stede, uanset om det var i den gemte blob. Tilføj en nøgle til defaults, og den optræder i hver eksisterende rækkes effektive præferencer automatisk, nestede nøgler inkluderet. Det blev rullet ind gennem en migrering, så eksisterende data fik gavnen med det samme frem for at vente på at blive skrevet om.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Resultat.&lt;/strong&gt; Præferencer kan vokse uden frygt. At tilføje en indstilling risikerer ikke længere et undefined‑felt‑crash i klienten, og frontenden holdt op med at have brug for defensive tjek spredt rundt om hvert sted, den læser en præference. Det gav også resten af platformen en pålidelig måde at udvide en hvilken som helst lagret JSON‑blob — mønsteret, ikke bare den ene rettelse.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Har bygget Python‑scraperne til skibsdata (MarineTraffic, Maritime‑Database) og et gentageligt import‑trin, der seeder platformens referencedata — 184.197 rækker, heraf 698 virksomheder og 56.149 skibe.</title>
    <id>https://data.engineer.company/da/portfolio/built-a-python-vessel-data-scraper-marinetraffic-maritime-66/</id>
    <link href="https://data.engineer.company/da/portfolio/built-a-python-vessel-data-scraper-marinetraffic-maritime-66/" rel="alternate" type="text/html" />
    <updated>2026-09-13T15:01:29+02:00</updated>
    <published>2026-09-13T15:01:29+02:00</published>
    <category term="Automatisering &amp; CI/CD" scheme="https://data.engineer.company/da/categories/" />
    <category term="Backend‑udvikling" scheme="https://data.engineer.company/da/categories/" />
    <category term="Data engineering" scheme="https://data.engineer.company/da/categories/" />
    <category term="Databaser" scheme="https://data.engineer.company/da/categories/" />
    <category term="Datapipelines (ETL/ELT)" scheme="https://data.engineer.company/da/categories/" />
    <category term="Python" scheme="https://data.engineer.company/da/categories/" />
    <category term="Backend- &amp; API‑udvikling" scheme="https://data.engineer.company/da/services/" />
    <category term="Udvikling af datapipelines (ETL/ELT)" scheme="https://data.engineer.company/da/services/" />
    <summary>Byggede Python-scrapere til skibsdata og seedede 184.197 rækker maritime referencedata — 698 virksomheder og 56.149 skibe — via en gentagelig pipeline.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Situation.&lt;/strong&gt; Et maritimt netværks- og anmeldelsessite er dødt ved ankomst, hvis det er tomt. Ingen melder sig ind i et katalog uden virksomheder i. Så før nogen af de sociale funktioner betød noget, havde platformen brug for et rigtigt korpus af maritime virksomheder og skibe, der allerede sad der, klar til at blive fundet.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Opgave.&lt;/strong&gt; Gå ud og hent de data — rigtige virksomheder og skibe, i nok skala til at føles befolket — og få dem ind i databasen på en måde, der kunne køres igen, ikke en engangs‑scrape, ingen ville kunne reproducere.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Handling.&lt;/strong&gt; Scraperne er skrevet i Python. Én driver MarineTraffic med Playwright; en anden henter fra Maritime‑Database over async httpx; der er også en ClassNK‑fetcher. De skriver CSV&amp;rsquo;er ud, og et import‑trin renser og normaliserer dem og indlæser dem i Postgres‑skemaet gennem en enkelt task, så at seede databasen er én kommando frem for en eftermiddags manuelt arbejde. Det, der gik ind, endte på 184.197 rækker: 698 virksomheder, 56.149 fartøjer og 33.074 byer, med en senere opdatering, der erstattede 74.794 fartøjsrækker.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Resultat.&lt;/strong&gt; Platformen blev lanceret med et befolket katalog i stedet for tomme tabeller og et grundlag af referencedata, som netværks-, job- og anmeldelsesfunktionerne alle kunne bygge oven på. Fordi pipelinen er reproducerbar, er det bare at køre den igen at opdatere eller udvide den senere — hvilket er sådan, fartøjsopdateringen skete, uden at nogen byggede værktøjet om. Scrapede data ældes, og at holde dem aktuelle er en løbende omkostning frem for et løst problem.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Har modelleret det maritime domæne i 348 normaliserede tabeller på tværs af 34 PostgreSQL‑skemaer — professionelle, virksomheder, skibe, jobs, anmeldelser og resten — med SMALLINT‑opslagstabeller og UUID v7‑nøgler.</title>
    <id>https://data.engineer.company/da/portfolio/modeled-the-maritime-domain-professionals-companies-ships-jobs-67/</id>
    <link href="https://data.engineer.company/da/portfolio/modeled-the-maritime-domain-professionals-companies-ships-jobs-67/" rel="alternate" type="text/html" />
    <updated>2026-09-13T15:01:29+02:00</updated>
    <published>2026-09-13T15:01:29+02:00</published>
    <category term="Data engineering" scheme="https://data.engineer.company/da/categories/" />
    <category term="Data governance" scheme="https://data.engineer.company/da/categories/" />
    <category term="Databaser" scheme="https://data.engineer.company/da/categories/" />
    <category term="Performanceoptimering" scheme="https://data.engineer.company/da/categories/" />
    <category term="Platformarkitektur" scheme="https://data.engineer.company/da/categories/" />
    <category term="PostgreSQL" scheme="https://data.engineer.company/da/categories/" />
    <category term="SQL" scheme="https://data.engineer.company/da/categories/" />
    <category term="Data governance &amp; datakvalitet" scheme="https://data.engineer.company/da/services/" />
    <category term="Databasedesign &amp; datamodellering" scheme="https://data.engineer.company/da/services/" />
    <category term="Platform- &amp; løsningsarkitektur" scheme="https://data.engineer.company/da/services/" />
    <summary>Modellerede det maritime domæne i 348 normaliserede tabeller på tværs af 34 PostgreSQL-skemaer — SMALLINT-opslag, UUID v7-nøgler og én navnekonvention.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Situation.&lt;/strong&gt; Hjertet i NextMariner er et tæt maritimt domæne — professionelle, virksomheder, skibe, jobs, anmeldelser — og de her ting refererer konstant til hinanden. En professionel sejler på skibe, arbejder for virksomheder, efterlader anmeldelser; en virksomhed ejer skibe og slår jobs op. Næsten hver funktion er en forespørgsel på tværs af det net, så hvor godt dataene er modelleret, afgør, hvor godt det meste af appen performer, og hvor fornuftigt det er at udvide den.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Opgave.&lt;/strong&gt; Det domæne skulle modelleres, så det holdt sig hurtigt og bevarede sin integritet, og så det at tilføje den næste entitetstype ikke betød at slås med skemaet.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Handling.&lt;/strong&gt; Det er lagt ud som normaliserede PostgreSQL‑skemaer organiseret efter domæne — 348 tabeller på tværs af 34 af dem efterhånden. De mange små, stabile enumerationer — statusser, typer, kategorier — blev SMALLINT‑opslagstabeller, hvilket holder rækkerne kompakte og joins billige i stedet for at gemme tekstkoder overalt. Entiteter får UUID v7‑primærnøgler, så de er globalt unikke, men stadig tidsordnet i indekset. Én navngivningskonvention løber hele vejen igennem — flertalstabeller inde i entalsnavngivne skemaer — anvendt uden undtagelse, hvilket som en bonus undgår en masse kollisioner med reserverede ord. Og relationerne holdes oppe af rigtige foreign keys og constraints, så integritet er databasens job, ikke noget applikationen skal huske at gøre.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Resultat.&lt;/strong&gt; Det, der kom ud, er en datamodel, der er konsistent og hurtig, og forudsigelig at arbejde i, fordi de samme regler holder overalt — der er ingen særtilfælde at huske. At tilføje en funktion betyder som regel at udvide skemaet med den eksisterende retning frem for imod den, hvilket er den eneste grund til, at 34 skemaer er en struktur frem for et vildnis. Det er gulvet, resten af platformen står på.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Har konfigureret opbevaring af databasebackups som infrastructure‑as‑code, gennemgået genopretningsberedskabet og dokumenteret restore‑proceduren — med de resterende huller navngivet frem for fundet under en hændelse.</title>
    <id>https://data.engineer.company/da/portfolio/configured-database-backup-retention-as-infrastructure-as-code-72/</id>
    <link href="https://data.engineer.company/da/portfolio/configured-database-backup-retention-as-infrastructure-as-code-72/" rel="alternate" type="text/html" />
    <updated>2026-09-13T15:01:29+02:00</updated>
    <published>2026-09-13T15:01:29+02:00</published>
    <category term="Cloud" scheme="https://data.engineer.company/da/categories/" />
    <category term="Databaser" scheme="https://data.engineer.company/da/categories/" />
    <category term="DevOps" scheme="https://data.engineer.company/da/categories/" />
    <category term="Drift &amp; backup" scheme="https://data.engineer.company/da/categories/" />
    <category term="Infrastruktur" scheme="https://data.engineer.company/da/categories/" />
    <category term="PostgreSQL" scheme="https://data.engineer.company/da/categories/" />
    <category term="Backup &amp; disaster recovery" scheme="https://data.engineer.company/da/services/" />
    <category term="Databaseadministration (DBA)" scheme="https://data.engineer.company/da/services/" />
    <category term="Infrastructure as Code" scheme="https://data.engineer.company/da/services/" />
    <summary>Implementerede databasebackups og en disaster recovery-strategi via infrastructure-as-code — hurtig, reproducerbar genopretning.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Situation.&lt;/strong&gt; Et produkt, der lever på sine data, har ikke råd til at miste nogen, og &amp;ldquo;der er backups et sted&amp;rdquo; er et håb, ikke en genopretningsplan. Den eneste backup, der er noget værd, er en, man ved gendanner, ind i et miljø, man ved, man kan genopbygge. NextMariner havde ingen af de to halvdele skrevet ned.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Opgave.&lt;/strong&gt; Få den genoprettelige position defineret i stedet for antaget — dataene, miljøet omkring dem, og et ærligt billede af, hvor langt det faktisk rækker i dag.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Handling.&lt;/strong&gt; Backup‑retention er konfigureret i Bicep ved siden af den database, den beskytter, så gendannelse til et tidspunkt er en egenskab ved templaten frem for en indstilling, nogen engang klikkede i en portal. Miljøet omkring den er også defineret som infrastructure‑as‑code, hvilket er den stille halvdel, folk glemmer: at gendanne en database ind i et miljø, man skulle genopbygge i hånden efter hukommelsen, er ikke rigtig genopretning. Derefter blev positionen gennemgået og skrevet op — gendannelsesproceduren, den øvelse, der ville måle den, og de huller, der stadig står åbne: geo‑redundans er slået fra, og målet for genopretningstid er foreslået frem for målt, fordi ingen øvelse er kørt endnu.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Resultat.&lt;/strong&gt; Genopretning holdt op med at være en vag beroligelse og blev en dokumenteret position med sine huller navngivet. Det lyder mindre imponerende end &amp;ldquo;disaster recovery: klaret&amp;rdquo;, og det er væsentligt mere værd — den næste, der rører ved det, ved, hvad der er dækket, hvad der ikke er, og præcis hvilken øvelse der lukker forskellen. Et navngivet hul kan man lukke; et unavngivet bliver opdaget under en hændelse.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Har leveret analyser og løbende statusrapporter til CEO&#39;en og omsat engineering‑metrikker og leveringsstatus til beslutninger.</title>
    <id>https://data.engineer.company/da/portfolio/delivered-analysis-and-regular-progress-reports-to-the-81/</id>
    <link href="https://data.engineer.company/da/portfolio/delivered-analysis-and-regular-progress-reports-to-the-81/" rel="alternate" type="text/html" />
    <updated>2026-09-13T15:01:29+02:00</updated>
    <published>2026-09-13T15:01:29+02:00</published>
    <category term="Dataanalyse" scheme="https://data.engineer.company/da/categories/" />
    <category term="Produkt &amp; krav" scheme="https://data.engineer.company/da/categories/" />
    <category term="Projektledelse" scheme="https://data.engineer.company/da/categories/" />
    <category term="Stakeholder &amp; rapportering" scheme="https://data.engineer.company/da/categories/" />
    <category term="Teknisk ledelse" scheme="https://data.engineer.company/da/categories/" />
    <category term="Dataanalyse &amp; BI‑dashboards" scheme="https://data.engineer.company/da/services/" />
    <category term="Projektledelse (Agile)" scheme="https://data.engineer.company/da/services/" />
    <category term="Teknisk ledelse &amp; rådgivning" scheme="https://data.engineer.company/da/services/" />
    <summary>Leverede analyser og løbende statusrapporter til CEO&#39;en — omsatte engineering-metrikker og leveringsstatus til trygge beslutninger.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Situation.&lt;/strong&gt; Efterhånden som platformen kom sammen, skulle dens fremdrift og tilstand være synlig for ledelsen i termer, de faktisk kunne gøre noget med. Rå engineering‑signaler — build‑status, leveringstempo, incidents — betyder ikke meget i sig selv for en, der træffer produkt- og investeringsvalg; de er i den forkerte højde. Nogen måtte oversætte.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Opgave.&lt;/strong&gt; Den oversættelse var jobbet: at tage engineering‑virkeligheden — hvor leveringen stod, hvad systemmetrikkerne sagde — og rapportere den til CEO&amp;rsquo;en klart og regelmæssigt, så beslutninger hvilede på fakta i stedet for gætværk.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Handling.&lt;/strong&gt; En fast rapporteringsrytme gik ind frem for at rapportere, når der blev spurgt, hvilket altid er en anelse for sent. Leveringsfremdriften, scope, risiciene og systemtilstanden blev fulgt og omsat til klare, beslutningsorienterede opdateringer — hvad der var på sporet, hvad der var i risiko, og hvad en given prioritet faktisk ville koste i afvejninger. Det, der skulle undgås, var at aflevere rå tal og overlade fortolkningen til nogen uden konteksten; hver rapport kom med konkrete anbefalinger, og hvor det hjalp, blev fortællingen understøttet af de underliggende analyser, så ledelsen kunne gå i dybden, hvis de ville, frem for at skulle tage det på tro.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Resultat.&lt;/strong&gt; Ledelsen endte med et klart, ærligt og aktuelt billede af engineering og kunne styre produktprioriteter og investeringer med en vis tillid i stedet for at flyve i blinde. Rapportering holdt op med at være et statusritual, ingen læser, og blev til noget, beslutninger faktisk blev truffet ud fra — hvilket holdt det tekniske arbejde og forretningsretningen pegende samme vej.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Har designet et tids- og rapporteringssystem, der forblev i produktion i årevis uden væsentlige ændringer.</title>
    <id>https://data.engineer.company/da/portfolio/designed-a-time-management-and-reporting-system-that-88/</id>
    <link href="https://data.engineer.company/da/portfolio/designed-a-time-management-and-reporting-system-that-88/" rel="alternate" type="text/html" />
    <updated>2026-09-13T15:01:29+02:00</updated>
    <published>2026-09-13T15:01:29+02:00</published>
    <category term="Automatisering &amp; CI/CD" scheme="https://data.engineer.company/da/categories/" />
    <category term="Produkt &amp; krav" scheme="https://data.engineer.company/da/categories/" />
    <category term="Projektledelse" scheme="https://data.engineer.company/da/categories/" />
    <category term="Teknisk ledelse" scheme="https://data.engineer.company/da/categories/" />
    <category term="Dataanalyse &amp; BI‑dashboards" scheme="https://data.engineer.company/da/services/" />
    <category term="Produktstrategi &amp; kravspecifikation" scheme="https://data.engineer.company/da/services/" />
    <category term="Projektledelse (Agile)" scheme="https://data.engineer.company/da/services/" />
    <summary>Designede et tids- og rapporteringssystem, der forblev i produktion i årevis uden væsentlige ændringer.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Situation.&lt;/strong&gt; Teamet havde ikke en pålidelig måde at styre tid og rapportere fremdrift på. Hvilket som regel betyder, at det sker i en spredning af regneark og hukommelse, og at rapporteringen bliver en kamp ved slutningen af hver periode frem for noget, der bare falder ud af, hvordan folk arbejder.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Opgave.&lt;/strong&gt; At bygge et system til begge dele, der faktisk ville holde, var opgaven.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Handling.&lt;/strong&gt; Et tids- og rapporteringssystem blev designet op omkring den måde, teamet reelt arbejdede på, frem for at påtvinge en hyldevareproces, de ville ruter uden om. Det er hele kunsten med interne værktøjer — hvis det passer til det virkelige workflow, bruger folk det; hvis det slås med workflowet, forlader de det stille og roligt, og man er tilbage ved regneark. Så det blev bygget til at matche virkeligheden frem for et ideal.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Resultat.&lt;/strong&gt; Det forblev i produktion i årevis uden nogen væsentlig ændring. Det er den kompliment, man vil have for et internt værktøj — ikke at det var imponerende, men at det bare blev ved med at virke, og ingen nogensinde behøvede at udskifte det. Noget, der overlever år med daglig brug urørt, var tydeligvis bygget til at passe.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Har bygget betalings- og rettighedslaget — Stripe side om side med Apple og Google in‑app purchase — så directory, søgning og eksport spærres af en adgangsmodel på 11 tabeller, der tjekkes på serveren.</title>
    <id>https://data.engineer.company/da/portfolio/built-the-payments-and-entitlements-layer-96/</id>
    <link href="https://data.engineer.company/da/portfolio/built-the-payments-and-entitlements-layer-96/" rel="alternate" type="text/html" />
    <updated>2026-09-13T15:01:29+02:00</updated>
    <published>2026-09-13T15:01:29+02:00</published>
    <category term="API&#39;er &amp; integration" scheme="https://data.engineer.company/da/categories/" />
    <category term="Backend‑udvikling" scheme="https://data.engineer.company/da/categories/" />
    <category term="Databaser" scheme="https://data.engineer.company/da/categories/" />
    <category term="PostgreSQL" scheme="https://data.engineer.company/da/categories/" />
    <category term="Produkt &amp; krav" scheme="https://data.engineer.company/da/categories/" />
    <category term="Sikkerhed" scheme="https://data.engineer.company/da/categories/" />
    <category term="Backend- &amp; API‑udvikling" scheme="https://data.engineer.company/da/services/" />
    <category term="Databasedesign &amp; datamodellering" scheme="https://data.engineer.company/da/services/" />
    <category term="Produktstrategi &amp; kravspecifikation" scheme="https://data.engineer.company/da/services/" />
    <category term="Sikkerhed &amp; adgangsstyring" scheme="https://data.engineer.company/da/services/" />
    <summary>Byggede betalings- og rettighedslaget — Stripe med Apple og Google in-app purchase — directory, søgning og eksport spærret af en adgangsmodel.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Situation.&lt;/strong&gt; Penge er den del af en platform, ingen har lov til at tage let på. Et abonnement skal overleve, at et kort udløber, en refusion, et planskifte, en webhook, der ankommer to gange, og en webhook, der ankommer i forkert rækkefølge. I det øjeblik betaling kan ske i tre butikker — et kort på nettet, Apple i den ene app store, Google i den anden — findes der tre forskellige udlægninger af, hvad nogen har købt, og produktet har stadig brug for ét svar på ét spørgsmål: hvad må denne person lige nu?&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Opgave.&lt;/strong&gt; At tage imod penge og at give adgang skulle være to systemer frem for ét, så det at tilføje en butik ikke betød at omskrive hver eneste gate i produktet.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Handling.&lt;/strong&gt; Stripe håndterer kort og abonnementer gennem 18 Go‑filer, og Apple- og Google‑in‑app‑køb kommer ind gennem deres egen kvitteringsverifikation. Alle tre løber sammen i et payments‑skema på 9 tabeller og 34 funktioner — og stopper så dér. Det, produktet faktisk spørger om, er et separat access‑skema på 11 tabeller og 34 funktioner, som svarer på &amp;ldquo;må denne konto det her?&amp;rdquo; uden at vide eller bryde sig om, hvilken butik der har betalt for det. Det svar styrer adgangen til virksomhedskataloget, søgningen og dataeksporten, og det genkontrolleres på serveren ved hver request, for en skjult knap er en høflighed og ikke en kontrol.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Resultat.&lt;/strong&gt; At tilføje en butik rører nu ved payments‑siden og lader alle gates være, og et supportspørgsmål om nogens adgang har én tabel at kigge i frem for tre. Omkostningen er to skemaer, hvor et mindre produkt ville nøjes med ét, plus et rettighedsopslag på requests, der ellers ville have været gratis.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Har flyttet langsomt arbejde væk fra request‑stien og over på en River‑jobkø — 15 worker‑moduler, 8 planlagte opgaver og 20 pg_cron‑jobs — så et request vender tilbage, mens arbejdet bag det kører videre.</title>
    <id>https://data.engineer.company/da/portfolio/moved-slow-work-onto-a-river-job-queue-97/</id>
    <link href="https://data.engineer.company/da/portfolio/moved-slow-work-onto-a-river-job-queue-97/" rel="alternate" type="text/html" />
    <updated>2026-09-13T15:01:29+02:00</updated>
    <published>2026-09-13T15:01:29+02:00</published>
    <category term="Automatisering &amp; CI/CD" scheme="https://data.engineer.company/da/categories/" />
    <category term="Backend‑udvikling" scheme="https://data.engineer.company/da/categories/" />
    <category term="Databaser" scheme="https://data.engineer.company/da/categories/" />
    <category term="Drift &amp; backup" scheme="https://data.engineer.company/da/categories/" />
    <category term="Performanceoptimering" scheme="https://data.engineer.company/da/categories/" />
    <category term="PostgreSQL" scheme="https://data.engineer.company/da/categories/" />
    <category term="Backend- &amp; API‑udvikling" scheme="https://data.engineer.company/da/services/" />
    <category term="Databasedesign &amp; datamodellering" scheme="https://data.engineer.company/da/services/" />
    <category term="Site reliability &amp; monitorering" scheme="https://data.engineer.company/da/services/" />
    <summary>Flyttede langsomt arbejde væk fra request-stien over på en River-jobkø: 15 worker-moduler, 8 planlagte opgaver og 20 pg_cron-vedligeholdelsesjobs.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Situation.&lt;/strong&gt; Noget arbejde har ingen gang på jorden, mens en bruger venter. At sende mail, at genopbygge et søgeindeks, at generere et dokument, at genberegne placeringer — gør noget af det inde i requesten, og brugeren kigger på en spinner for noget, de aldrig bad om at se. Gør det i stedet i en goroutine, og det forsvinder i det øjeblik processen genstarter, hvilket den gør, midt i en deploy, uden spor af, at det nogensinde skulle være sket.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Opgave.&lt;/strong&gt; Baggrundsarbejde havde brug for et holdbart sted at bo: en kø, der overlever en genstart, prøver en fejl igen og kan kigges efter, når noget ikke er sket.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Handling.&lt;/strong&gt; Valget faldt på River, i høj grad fordi den holder sin kø i PostgreSQL — databasen er i forvejen det autoritative register, så et job og de rækker, det rører, committer eller ruller tilbage sammen, og der er ikke et stykke infrastruktur nummer to at køre og ræsonnere om. Bag den ligger 15 worker‑moduler og 8 planlagte opgaver. Under det håndterer 20 pg_cron‑jobs den vedligeholdelse, databasen er bedre placeret til at gøre selv: at beskære partitioner, at rotere salts, at opfriske aggregater. Alt, der var langsomt nok til at blive bemærket, blev flyttet væk fra request‑stien og over på en af de to.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Resultat.&lt;/strong&gt; Requests svarer hurtigt, og det langsomme arbejde bliver stadig færdigt, med retries og en synlig historik, når det ikke gør. At holde køen i Postgres frem for i en dedikeret broker er en bevidst begrænsning: det skalerer ikke i det uendelige, og ved en vis mængde bliver det det forkerte svar. For en platform, hvis flaskehals alligevel er databasen, var én bevægelig del mindre mere værd end luft, der ikke ville blive brugt.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Har holdt skemaet ærligt på tværs af 1.022 migrationer med en CI‑gate, der bygger databasen begge veje — en frisk installation og en installation plus hver eneste migration — og fejler, når de to ikke stemmer overens.</title>
    <id>https://data.engineer.company/da/portfolio/kept-the-schema-honest-across-1022-migrations-99/</id>
    <link href="https://data.engineer.company/da/portfolio/kept-the-schema-honest-across-1022-migrations-99/" rel="alternate" type="text/html" />
    <updated>2026-09-13T15:01:29+02:00</updated>
    <published>2026-09-13T15:01:29+02:00</published>
    <category term="Data governance" scheme="https://data.engineer.company/da/categories/" />
    <category term="Databaser" scheme="https://data.engineer.company/da/categories/" />
    <category term="DevOps" scheme="https://data.engineer.company/da/categories/" />
    <category term="Drift &amp; backup" scheme="https://data.engineer.company/da/categories/" />
    <category term="Migrering &amp; modernisering" scheme="https://data.engineer.company/da/categories/" />
    <category term="PostgreSQL" scheme="https://data.engineer.company/da/categories/" />
    <category term="Test &amp; QA" scheme="https://data.engineer.company/da/categories/" />
    <category term="Databaseadministration (DBA)" scheme="https://data.engineer.company/da/services/" />
    <category term="Databasemigrering &amp; modernisering" scheme="https://data.engineer.company/da/services/" />
    <category term="DevOps &amp; CI/CD‑automatisering" scheme="https://data.engineer.company/da/services/" />
    <summary>Holdt skemaet ærligt på tværs af 1.022 migrationer med en CI-gate, der bygger databasen begge veje og fejler, når de to ikke stemmer overens.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Situation.&lt;/strong&gt; Et skema er beskrevet to gange i de fleste projekter: én gang af den indledende opsætning, der bygger det fra bunden, og én gang af de ophobede migrationer, der har fået det til at vokse. Begge er ment at producere den samme database. Intet tjekker, at de gør det, så de driver fra hinanden — og afdriften er usynlig, indtil et friskt miljø opfører sig anderledes end produktion, som regel på det værst tænkelige tidspunkt.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Opgave.&lt;/strong&gt; De to beskrivelser skulle beviseligt være identiske, automatisk, frem for periodisk at blive troet at være det.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Handling.&lt;/strong&gt; Databasen er versioneret som 1.022 migrationer, nummereret fra 036 til 1102, og rækkefølgedisciplinen omkring dem er kedelig og ikke til forhandling. Det, der får den til at holde, er et CI‑job, der bygger databasen to gange ved hver ændring: én gang fra det friske initielle skema, én gang fra det initielle skema plus hver eneste migration afspillet i rækkefølge — og så sammenligner de to. Ikke bare strukturen, som er den nemme halvdel, men også de seedede data, for en migration, der backfiller en opslagstabel forkert, er præcis lige så skadelig som en, der glemmer en kolonne, og kun den ene af dem dukker op i en skema‑diff. Enhver uenighed får buildet til at fejle med forskellen printet ud.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Resultat.&lt;/strong&gt; Et friskt miljø og et langtlevende er den samme database, og det bliver tjekket frem for antaget. Omkostningen lander hos den, der skriver en migration: den skal virke afspillet, og den skal virke fra koldt, hvilket er mere tanke, end et hurtigt ALTER som regel får. Det er netop pointen — alternativet er at finde ud af det under en gendannelse, hvor svaret betyder noget, og der ikke er tid til at regne det ud.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Har bygget egen produktanalyse i PostgreSQL — 47 funktioner over partitionerede event‑tabeller, der selv rydder op — pseudonymiseret bag et roterende salt og betinget af den besøgendes samtykke.</title>
    <id>https://data.engineer.company/da/portfolio/built-first-party-product-analytics-in-postgresql-101/</id>
    <link href="https://data.engineer.company/da/portfolio/built-first-party-product-analytics-in-postgresql-101/" rel="alternate" type="text/html" />
    <updated>2026-09-13T15:01:29+02:00</updated>
    <published>2026-09-13T15:01:29+02:00</published>
    <category term="Data engineering" scheme="https://data.engineer.company/da/categories/" />
    <category term="Data governance" scheme="https://data.engineer.company/da/categories/" />
    <category term="Databaser" scheme="https://data.engineer.company/da/categories/" />
    <category term="Dataanalyse" scheme="https://data.engineer.company/da/categories/" />
    <category term="Performanceoptimering" scheme="https://data.engineer.company/da/categories/" />
    <category term="PostgreSQL" scheme="https://data.engineer.company/da/categories/" />
    <category term="SQL" scheme="https://data.engineer.company/da/categories/" />
    <category term="Data governance &amp; datakvalitet" scheme="https://data.engineer.company/da/services/" />
    <category term="Databasedesign &amp; datamodellering" scheme="https://data.engineer.company/da/services/" />
    <category term="Dataanalyse &amp; BI‑dashboards" scheme="https://data.engineer.company/da/services/" />
    <category term="Udvikling af datapipelines (ETL/ELT)" scheme="https://data.engineer.company/da/services/" />
    <summary>Byggede egen produktanalyse i PostgreSQL — 47 funktioner over partitionerede tabeller, der selv rydder op — pseudonymiseret og betinget af samtykke.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Situation.&lt;/strong&gt; Produktbeslutninger har brug for tal, og den almindelige måde at få dem på er at sætte et third‑party‑tag på hver side og lade en andens servere holde øje med brugerne. Det er hurtigt, det er gratis ved små mængder, og det betyder, at besøgendes adfærd på en professionel netværksplatform — hvem der kiggede på hvilken virksomhed, hvem der søgte efter hvad — bliver et aktiv, en annoncevirksomhed sidder på. For en platform, hvis brugere er identificerbare maritime professionelle, er det en dårlig handel.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Opgave.&lt;/strong&gt; Produktteamet havde brug for funnels, retention og eventdata, indsamlet på en måde, platformen kunne stå inde for, og en bruger kunne sige nej til.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Handling.&lt;/strong&gt; Analytics kom til at ligge i PostgreSQL, i et skema på 7 tabeller og 47 funktioner. Event‑tabellerne er partitionerede — 22 partition‑definitioner — og rydder ud i sig selv på en tidsplan, for prisen ved first‑party analytics er ikke at indsamle events, den er at gemme dem for evigt. Identitet er pseudonymiseret bag et salt, der roterer, så en besøgende ikke kan følges hen over rotationsgrænsen, end ikke indefra databasen; det er et bevidst loft over, hvad dataene kan svare på. Klienten kender samtykkestatus og sender intet, før samtykke er givet, frem for at sende og filtrere bagefter. Konverteringsfunnels beregnes i databasen, ved siden af dataene, i stedet for at blive eksporteret et andet sted hen for at blive joinet tilbage.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Resultat.&lt;/strong&gt; Spørgsmål om, hvordan produktet bruges, besvares fra platformens egne tabeller, uden at noget forlader den, og uden et tag i siden. Begrænsningerne er den ærlige del: at rotere saltet koster kohorteanalyse over lange horisonter, og intet af det her kommer med de dashboards, et hosted værktøj giver dig gratis. Begge dele blev accepteret med åbne øjne.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Har bygget loyalitets- og omdømmesystemet — 67 funktioner over et ledger på 31 tabeller, med ligaer, badges og en indløsningsshop — med en row lock på saldoen, der lukker double‑spend‑vinduet.</title>
    <id>https://data.engineer.company/da/portfolio/built-the-loyalty-and-reputation-system-105/</id>
    <link href="https://data.engineer.company/da/portfolio/built-the-loyalty-and-reputation-system-105/" rel="alternate" type="text/html" />
    <updated>2026-09-13T15:01:29+02:00</updated>
    <published>2026-09-13T15:01:29+02:00</published>
    <category term="Backend‑udvikling" scheme="https://data.engineer.company/da/categories/" />
    <category term="Databaser" scheme="https://data.engineer.company/da/categories/" />
    <category term="Performanceoptimering" scheme="https://data.engineer.company/da/categories/" />
    <category term="PostgreSQL" scheme="https://data.engineer.company/da/categories/" />
    <category term="Produkt &amp; krav" scheme="https://data.engineer.company/da/categories/" />
    <category term="SQL" scheme="https://data.engineer.company/da/categories/" />
    <category term="Backend- &amp; API‑udvikling" scheme="https://data.engineer.company/da/services/" />
    <category term="Databasedesign &amp; datamodellering" scheme="https://data.engineer.company/da/services/" />
    <category term="Produktstrategi &amp; kravspecifikation" scheme="https://data.engineer.company/da/services/" />
    <summary>Byggede loyalitets- og omdømmesystemet — 67 funktioner over et ledger på 31 tabeller, ligaer, badges og en shop — med row lock på saldoen.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Situation.&lt;/strong&gt; Professionelt netværk har et cold start‑problem: platformen er værd at bruge, når andre allerede bruger den, og indtil da er der ikke meget grund til at komme tilbage. Den sædvanlige løftestang er et belønningssystem — point for at bidrage, en standing der afspejler omdømme — som er nemt at beskrive og lumsk at bygge, for i det øjeblik point kan bruges, er de penge, og hver eneste fejl, penge kan lave, kan laves her.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Opgave.&lt;/strong&gt; Bidrag skulle kunne måles og belønnes, med en saldo, der ikke kunne bruges to gange.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Handling.&lt;/strong&gt; Loyalty‑skemaet løber op i 31 tabeller og 67 funktioner, med standing i yderligere 5 tabeller og 32 funktioner, og discovery- og personalization‑skemaer ved siden af til at afgøre, hvad et givent medlem ser. Oven på ledgeren sidder ligaer, badges og en indløsningsshop, hvor en saldo bliver til noget virkeligt. Det, der krævede omhuen, er den ældste fejl i bogen: tjek saldoen, brug den så, og to requests, der ankommer samtidig, passerer begge tjekket. Hver mutation tager en row lock på walleten, før den læser den, så den anden request venter på, at den første bliver færdig, frem for at kappes med den. At walleten ligger i den samme database som alt andet er det, der overhovedet gør det muligt — saldoen og det, den købte, committer sammen eller slet ikke.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Resultat.&lt;/strong&gt; Bidrag bliver målt og belønnet, og en saldo er et regnestykke frem for en tilnærmelse. Row locking er det langsommere svar og blev valgt alligevel: kamp om den samme wallet bliver til en kø, og alternativet er et medlem, der bruger de samme point to gange, og nogen, der afstemmer det i hånden bagefter.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Har bygget rekrutteringsmarkedspladsen og søfarendes karriere‑workspace — 151 stored functions på tværs af 48 tabeller — med ledige stillinger, ansøgninger, certifikater, avancement i grader og verificeret sejltid.</title>
    <id>https://data.engineer.company/da/portfolio/built-the-hiring-marketplace-and-career-workspace-107/</id>
    <link href="https://data.engineer.company/da/portfolio/built-the-hiring-marketplace-and-career-workspace-107/" rel="alternate" type="text/html" />
    <updated>2026-09-13T15:01:29+02:00</updated>
    <published>2026-09-13T15:01:29+02:00</published>
    <category term="Backend‑udvikling" scheme="https://data.engineer.company/da/categories/" />
    <category term="Data governance" scheme="https://data.engineer.company/da/categories/" />
    <category term="Databaser" scheme="https://data.engineer.company/da/categories/" />
    <category term="Full stack‑udvikling" scheme="https://data.engineer.company/da/categories/" />
    <category term="PostgreSQL" scheme="https://data.engineer.company/da/categories/" />
    <category term="Produkt &amp; krav" scheme="https://data.engineer.company/da/categories/" />
    <category term="Backend- &amp; API‑udvikling" scheme="https://data.engineer.company/da/services/" />
    <category term="Databasedesign &amp; datamodellering" scheme="https://data.engineer.company/da/services/" />
    <category term="Full stack‑produktudvikling" scheme="https://data.engineer.company/da/services/" />
    <category term="Produktstrategi &amp; kravspecifikation" scheme="https://data.engineer.company/da/services/" />
    <summary>Byggede jobmarkedspladsen og søfarendes karriereområde — 151 stored functions på tværs af 48 tabeller — stillinger matchet på dokumenterede kvalifikationer.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Situation.&lt;/strong&gt; Det kommercielle argument for et maritimt professionelt netværk er rekruttering: virksomheder har brug for besætning og officerer, og søfarende har brug for hyre. Begge halvdele fandtes allerede på platformen i den forkerte form — virksomhederne lå i kataloget, de professionelle havde profiler, og der var intet, der forbandt en ledig stilling med den person, der var kvalificeret til at udfylde den. Kvalifikationen er den svære del, for i denne branche er det certifikater, grader og dokumenteret sejltid frem for en jobtitel.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Opgave.&lt;/strong&gt; Ledige stillinger, ansøgninger og verificerbare kvalifikationsbeviser for søfarende skulle modelleres ordentligt frem for som fritekst på en profil.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Handling.&lt;/strong&gt; To domæner blev bygget. Rekrutteringssiden løber op i 32 tabeller og 118 funktioner, der dækker ledige stillinger, ansøgninger, shortlisting og arbejdsgiverens billede af en pipeline. Karriere‑workspacet bærer 16 tabeller og 33 funktioner, der rummer certifikater, gradprogression og sejltid, med dokumentupload og en gennemgangskø, så et kvalifikationsbevis bliver kontrolleret frem for påstået. At modellere progression som en graf frem for en liste er det, der gør matchningen brugbar — en grad er nåelig fra en anden grad givet bestemte certifikater og nok registreret tid til søs, og den struktur er det, der lader en ledig stilling blive matchet mod en karriere frem for mod et nøgleord. Karriere‑workspacet sendes bag et feature flag og er ikke fuldt released; rekrutteringssiden er live.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Resultat.&lt;/strong&gt; En ledig stilling kan matches mod dokumenterede kvalifikationer i stedet for en selvbeskrevet jobtitel, og det er hele forskellen mellem et jobopslagssite og et rekrutteringsværktøj i denne branche. Verifikationen er flaskehalsen, med vilje — en gennemgangskø skalerer ikke, som et automatisk tjek ville, og et automatisk tjek ville certificere folk, der ikke burde certificeres.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Har skrevet en scoperegel ind i kodebasen, efter at en omstrukturering bar en anden virksomheds inventar, firewalltilladelser og prosa med ind i den — og har holdt det karantæneramte restmateriale under hemmelighedsscanneren frem for at udelukke det.</title>
    <id>https://data.engineer.company/da/portfolio/wrote-a-scope-rule-after-a-credential-leak-124/</id>
    <link href="https://data.engineer.company/da/portfolio/wrote-a-scope-rule-after-a-credential-leak-124/" rel="alternate" type="text/html" />
    <updated>2026-09-13T15:01:29+02:00</updated>
    <published>2026-09-13T15:01:29+02:00</published>
    <category term="Automatisering &amp; CI/CD" scheme="https://data.engineer.company/da/categories/" />
    <category term="Data governance" scheme="https://data.engineer.company/da/categories/" />
    <category term="Dokumentation" scheme="https://data.engineer.company/da/categories/" />
    <category term="Infrastruktur" scheme="https://data.engineer.company/da/categories/" />
    <category term="Sikkerhed" scheme="https://data.engineer.company/da/categories/" />
    <category term="Data governance &amp; datakvalitet" scheme="https://data.engineer.company/da/services/" />
    <category term="Sikkerhed &amp; adgangsstyring" scheme="https://data.engineer.company/da/services/" />
    <category term="Teknisk dokumentation" scheme="https://data.engineer.company/da/services/" />
    <summary>Omfangsgrænsen er en skreven regel med en oplyst test, resterne er synlige frem for begravet, og den konkrete form for legitimationsoplysning der slap igennem,…</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Situation.&lt;/strong&gt; Arbejde udført for en anden virksomhed kørte med gennem en omstrukturering af repositoryet og blev liggende. Det der fulgte med var ikke abstrakt: en kladdelog med levende legitimationsoplysninger i klartekst, som lå i træet forbi hver eneste vagtpost gennem det meste af repositoryets historie; en forældet inventarliste der navngav den virksomheds vært; og en firewall‑opgavefil der åbnede porte til seksten af dens kundenetværk. Intet af det kørte. Det er præcis derfor det overlevede — noget der ikke kører nogen steder, bliver aldrig gennemgået igen.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Opgave.&lt;/strong&gt; Grænsen skulle blive til en regel med en test knyttet til sig frem for en hensigt, og resterne skulle håndteres på en måde, der ikke blot skjulte dem.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Handling.&lt;/strong&gt; Reglen er nu åbningsafsnittet i repositoryets instruktionssæt: dette repository håndterer én virksomheds infrastruktur og kun den, og en anden parts vært, inventarliste, firewalltilladelse, DNS‑zone eller legitimationsoplysning hører ikke hjemme i det — ikke engang deaktiveret, udkommenteret eller parkeret i en fil, ingen playbook importerer. Den praktiske test står ved siden af: ville denne virksomhed stadig være ansvarlig for dette, hvis forholdet ophørte. Resterne blev sat i karantæne i et tydeligt navngivet katalog frem for slettet, så historikken forbliver læselig, og karantænen er bevidst delvis — de to strukturelle linters springer den over, og hemmelighedsskanneren, boksvagten og emoji‑tjekket læser den bevidst stadig, for det er de tre, der ville fange det, der slap ind. Selve lækagen frembragte en linterregel: et brugerdefineret mønster der markerer en legitimationsoplysning sendt som et kommandolinjeflag, hvilket er den form den lækkede havde, og som standardregelsættet ikke matchede.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Resultat.&lt;/strong&gt; Omfangsgrænsen er en skreven regel med en oplyst test, resterne er synlige frem for begravet, og den konkrete form for legitimationsoplysning der slap igennem, fejler nu et commit. Læren noteret ved siden af er den generelle: det farlige artefakt er ikke det der kører, det er det der ikke gør, for det er det, ingen læser igen.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Har genereret 495 achievement‑sider på tre sprog fra en skrivebeskyttet SQLite‑eksport, med sidens adresse forfattet som data, så en rettet sætning ikke længere flyttede siden og brød linket.</title>
    <id>https://data.engineer.company/da/portfolio/generated-321-achievement-pages-from-a-sqlite-export-132/</id>
    <link href="https://data.engineer.company/da/portfolio/generated-321-achievement-pages-from-a-sqlite-export-132/" rel="alternate" type="text/html" />
    <updated>2026-09-13T15:01:29+02:00</updated>
    <published>2026-09-13T15:01:29+02:00</published>
    <category term="Databaser" scheme="https://data.engineer.company/da/categories/" />
    <category term="Datapipelines (ETL/ELT)" scheme="https://data.engineer.company/da/categories/" />
    <category term="Frontend‑udvikling" scheme="https://data.engineer.company/da/categories/" />
    <category term="Internationalisering" scheme="https://data.engineer.company/da/categories/" />
    <category term="Python" scheme="https://data.engineer.company/da/categories/" />
    <category term="SQL" scheme="https://data.engineer.company/da/categories/" />
    <category term="Webudvikling" scheme="https://data.engineer.company/da/categories/" />
    <category term="Brand, marketing &amp; SEO" scheme="https://data.engineer.company/da/services/" />
    <category term="Internationalisering &amp; lokalisering" scheme="https://data.engineer.company/da/services/" />
    <category term="Udvikling af datapipelines (ETL/ELT)" scheme="https://data.engineer.company/da/services/" />
    <category term="Webstedsudvikling &amp; CMS" scheme="https://data.engineer.company/da/services/" />
    <summary>Fire hundrede og femoghalvfems sider genereres fra én kilde, at rette et udsagn koster intet, og de adresser dette site nogensinde har udgivet, svarer fortsat.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Situation.&lt;/strong&gt; Virksomhedens porteføljeindhold skrives i en særskilt database — den samme der frembringer CV&amp;rsquo;et — og websitet skal udgive det som sider, på tre sprog, uden at de to kopier driver fra hinanden. Den naive tilgang, at skrive siderne i hånden og holde dem i takt, fejler ved den første rettelse.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Opgave.&lt;/strong&gt; Websitet skulle generere sit indhold fra databasen som et byggeinput, med sideadresser der overlever, at sætningerne på dem bliver skrevet om.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Handling.&lt;/strong&gt; En eksportør læser databasen skrivebeskyttet og skriver én side per achievement per sprog — 495 sider — plus de taksonomi- og ydelsesdata skabelonerne har brug for. Den bruger kun standardbiblioteket, så sitets bygning ikke afhænger af generatorens miljø, og det committede output betyder, at sitet bygger selvstændigt. Den mest konsekvensrige beslutning i den handler om adresser. Sitet plejede at udlede en sides URL fra de indledende ord i dens engelske udsagn, så at rette en sætning flyttede tavst siden og ødelagde hvert link til den — et site hvis argument for sig selv er, at det retter ting, og som opkrævede sig selv et dødt link, hver gang det gjorde. Adressen skrives nu som data: én række per adresse per achievement, den første er den aktuelle, og hver senere er en pensioneret adresse, sitet udsender som en omdirigering. To andre fælder er noteret fra det samme arbejde. En periodesammenligning mod en tekstkolonne matchede tavst alle toogtredive rækker på grund af, hvordan databasen tildeler typeaffinitet på tværs af en sammenligning. Og sproglisten er nu den ene akse, som skriveløkken, datafilerne og forespørgslerne alle udledes af, så at tilføje et fjerde sprog er én opslagspost frem for en søgning.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Resultat.&lt;/strong&gt; Fire hundrede og femoghalvfems sider genereres fra én kilde, at rette et udsagn koster intet, og de adresser dette site nogensinde har udgivet, svarer fortsat. Eksportøren ejer også præcis én præsentationsbeslutning — hvordan ydelser grupperes i tematiske afsnit — og det er bevidst: alt andet den skriver, tilhører databasen, og en gruppeoverskrift der mangler et sprog, fejler eksporten frem for at gengive engelsk oven på oversat indhold.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Har erstattet 963 anonyme blokke med strukturerede data, der gentog virksomheden 1.671 gange, med én sammenkædet graf af 16 typer præget fra stabile oprindelsesidentifikatorer.</title>
    <id>https://data.engineer.company/da/portfolio/replaced-963-structured-data-blocks-with-one-graph-138/</id>
    <link href="https://data.engineer.company/da/portfolio/replaced-963-structured-data-blocks-with-one-graph-138/" rel="alternate" type="text/html" />
    <updated>2026-09-13T15:01:29+02:00</updated>
    <published>2026-09-13T15:01:29+02:00</published>
    <category term="API&#39;er &amp; integration" scheme="https://data.engineer.company/da/categories/" />
    <category term="Automatisering &amp; CI/CD" scheme="https://data.engineer.company/da/categories/" />
    <category term="Brand &amp; marketing" scheme="https://data.engineer.company/da/categories/" />
    <category term="Data governance" scheme="https://data.engineer.company/da/categories/" />
    <category term="Frontend‑udvikling" scheme="https://data.engineer.company/da/categories/" />
    <category term="Webudvikling" scheme="https://data.engineer.company/da/categories/" />
    <category term="Brand, marketing &amp; SEO" scheme="https://data.engineer.company/da/services/" />
    <category term="Data governance &amp; datakvalitet" scheme="https://data.engineer.company/da/services/" />
    <category term="Webstedsudvikling &amp; CMS" scheme="https://data.engineer.company/da/services/" />
    <summary>Én graf med stabil identitet erstatter 963 anonyme gentagelser, og siderne bærer mindre frem for mere.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Situation.&lt;/strong&gt; Sitet udsendte strukturerede data på den måde de fleste sites gør: en blok per side, hver af dem beskrev organisationen forfra igen. På tværs af sitet blev det til 963 blokke, der gentog den samme virksomhed 1.671 gange, anonymt — ingen stabil identifikator nogen steder, så intet der forbrugte det, kunne se at organisationen på én side var organisationen på en anden.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Opgave.&lt;/strong&gt; De strukturerede data skulle blive én graf med stabil identitet frem for en bunke blokke, der tilfældigvis indeholder de samme ord.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Handling.&lt;/strong&gt; Identifikatorer udstedes nu fra sitets oprindelse — én til organisationen, én til sitet, én til personen — og hver blok refererer til dem frem for at gentage deres indhold. Identifikatorerne er fælles for oprindelsen frem for per sprog, for virksomheden er den samme virksomhed på dansk. Seksten typer er i spil og dækker ydelseskataloget og dets tilbud, anmeldelserne og det arbejde de beskriver, samlingerne og deres brødkrummer. To beslutninger holdt vægten nede. Oversigtssider udgiver deres elementer kun ved URL frem for at indlejre dem, hvilket blev målt: at navngive dem på porteføljeoversigten ville have betydet 107 fulde udsagn og en stigning på 52 procent i den komprimerede side. Og det tjek der vogter det, validerer ikke blot syntaks — det efterprøver at hver blok kan parses, at hver identifikator resolverer, og at hver URL grafen navngiver, faktisk blev bygget, så en graf der peger på en side der ikke findes, fejler gaten.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Resultat.&lt;/strong&gt; Én graf med stabil identitet erstatter 963 anonyme gentagelser, og siderne bærer mindre frem for mere. Den måling der satte arbejdet i gang, er værd at holde sig for øje: sitet havde udsendt den samme organisationsbeskrivelse 1.671 gange, uden at noget var i stand til at føje dem sammen.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Har bygget en databasedrevet generator til CV, referencer, portefølje og ansøgninger i Python — 41 moduler, 10.580 linjer — der gengiver seks outputformater fra én SQLite‑kilde med 23 tabeller samlet af en idempotent pipeline i 19 trin.</title>
    <id>https://data.engineer.company/da/portfolio/built-a-database-driven-cv-and-portfolio-generator-144/</id>
    <link href="https://data.engineer.company/da/portfolio/built-a-database-driven-cv-and-portfolio-generator-144/" rel="alternate" type="text/html" />
    <updated>2026-09-13T15:01:29+02:00</updated>
    <published>2026-09-13T15:01:29+02:00</published>
    <category term="Automatisering &amp; CI/CD" scheme="https://data.engineer.company/da/categories/" />
    <category term="Backend‑udvikling" scheme="https://data.engineer.company/da/categories/" />
    <category term="Databaser" scheme="https://data.engineer.company/da/categories/" />
    <category term="Full stack‑udvikling" scheme="https://data.engineer.company/da/categories/" />
    <category term="Internationalisering" scheme="https://data.engineer.company/da/categories/" />
    <category term="Løsningsarkitektur" scheme="https://data.engineer.company/da/categories/" />
    <category term="Python" scheme="https://data.engineer.company/da/categories/" />
    <category term="SQL" scheme="https://data.engineer.company/da/categories/" />
    <category term="Backend- &amp; API‑udvikling" scheme="https://data.engineer.company/da/services/" />
    <category term="Databasedesign &amp; datamodellering" scheme="https://data.engineer.company/da/services/" />
    <category term="Full stack‑produktudvikling" scheme="https://data.engineer.company/da/services/" />
    <category term="Internationalisering &amp; lokalisering" scheme="https://data.engineer.company/da/services/" />
    <category term="Platform- &amp; løsningsarkitektur" scheme="https://data.engineer.company/da/services/" />
    <summary>Seks formater, tre sprog og fem temaer kommer ud af én database, og en rettet sætning rettes én gang.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Situation.&lt;/strong&gt; Et CV, et referenceark, en portefølje og en ansøgning er de samme fakta arrangeret på fire måder, og at holde dem som fire dokumenter betyder, at hver rettelse foretages fire gange og til sidst ikke gør. Tre sprog ganger det med tre. Fejltilstanden er ikke, at et dokument er forkert; det er, at to dokumenter er uenige, og intet siger hvilket der er det aktuelle.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Opgave.&lt;/strong&gt; Én kilde til fakta skulle frembringe hvert dokument, på hvert sprog, i hvert format, med arrangementet afgjort af kode frem for af den, der sidst redigerede en fil.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Handling.&lt;/strong&gt; Kilden er en SQLite‑database med treogtyve tabeller — achievements, titler, virksomheder, regioner, kategorier, ydelser, profiler, referencer, resuméer — samlet af en pipeline i nitten trin, der kører fra en tom fil til en komplet database med én kommando. Trinnene er ordnede, og hvert er skrevet til at være sikkert at gentage, så pipelinen kan køres mod en eksisterende database uden at duplikere en række. Enogfyrre Python‑moduler på i alt 10.580 linjer gengiver seks outputformater fra den: HTML, PDF i to varianter, ren tekst, Markdown og JSON, gennem seks Jinja‑skabeloner og otte stylesheets. Kørselsafhængigheder blev holdt til præcis to, en skabelonmotor og en PDF‑gengiver, ud fra det argument at en dokumentgenerator, som ikke kan installeres om fem år, ikke har bevaret noget. Målretning er et førsteklasses begreb frem for en manuel redigering: en profil vælger hvilke achievements der optræder og i hvilken rækkefølge, så et dokument rettet mod én slags læser er en forespørgsel frem for en kopi.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Resultat.&lt;/strong&gt; Seks formater, tre sprog og fem temaer kommer ud af én database, og en rettet sætning rettes én gang. Prisen er, at systemet nu er den eneste måde at frembringe et dokument på — der er ikke længere en fil at åbne og redigere i en fart, og at tilføje et sprog betyder at tilføje det overalt, før noget som helst bygger.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Har skrevet tests af selve tjekkene efter at have fastslået, at et tjek, der kun fodres med rent input, en dag melder rent, fordi det intet læste — ved at plante en stavefejl for at bekræfte, at stavekontrollen finder den, og ved at tage et id‑interval fra databasen frem for fra et tal i testen.</title>
    <id>https://data.engineer.company/da/portfolio/wrote-tests-for-the-checkers-themselves-149/</id>
    <link href="https://data.engineer.company/da/portfolio/wrote-tests-for-the-checkers-themselves-149/" rel="alternate" type="text/html" />
    <updated>2026-09-13T15:01:29+02:00</updated>
    <published>2026-09-13T15:01:29+02:00</published>
    <category term="Automatisering &amp; CI/CD" scheme="https://data.engineer.company/da/categories/" />
    <category term="Data governance" scheme="https://data.engineer.company/da/categories/" />
    <category term="Databaser" scheme="https://data.engineer.company/da/categories/" />
    <category term="Python" scheme="https://data.engineer.company/da/categories/" />
    <category term="Test &amp; QA" scheme="https://data.engineer.company/da/categories/" />
    <category term="Data governance &amp; datakvalitet" scheme="https://data.engineer.company/da/services/" />
    <category term="DevOps &amp; CI/CD‑automatisering" scheme="https://data.engineer.company/da/services/" />
    <category term="Teknisk ledelse &amp; rådgivning" scheme="https://data.engineer.company/da/services/" />
    <summary>Hvert tjek i projektet har nu en test, der beviser, at det fejler på dårlige inddata, og områdeforventningerne læses fra sandhedskilden.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Situation.&lt;/strong&gt; Projektet kører en række egne tjek over sit eget indhold — en stavekontrol, et tjek af identifikatorernes talområde, et stemmetjek, et tjek af taloverensstemmelse. Hvert af dem havde kørt grønt i månedsvis. Et tjek, der kun nogensinde har set rene inddata og kun nogensinde har meldt rent, kan ikke skelnes fra et tjek, der slet intet læser, og der fandtes ingen test i suiten, som kunne kende forskel på de to.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Opgave.&lt;/strong&gt; Tjekkene skulle bringes til at bevise, at de kan fejle, og de fikstursdata, de tjekker imod, skulle holde op med at være håndholdte kopier af det, de beskriver.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Handling.&lt;/strong&gt; Mønsteret, der er anvendt hele vejen igennem, er at plante netop den defekt, tjekket findes for at fange, og kræve at tjekket finder den. Stavekontrollen fodres med et bevidst fejlstavet ord, og testen fejler, hvis kørslen kommer rent tilbage. Stemmetjekket fodres med prosa i første person og skal afvise den. Buzzword‑tjekket fodres med et forbudt ord. Hvert af disse er en lille test, og hver af dem lukkede en reel blind vinkel, for to af tjekkene viste sig at læse et snævrere sæt filer end deres dokumentation påstod og havde tavst sprunget indhold over. Den anden ændring handler om, hvor en test henter sine forventninger: tjekket af identifikatorernes talområde sammenlignede før med et tal skrevet i testfilen, hvilket betød, at enhver tilføjelse af indhold krævede en redigering af en test, og en redaktør, der opdaterede tallet uden at se efter, havde slået tjekket fra. Det udleder nu området fra databasen, så tjekket beskriver dataene frem for en forældet erindring om dem.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Resultat.&lt;/strong&gt; Hvert tjek i projektet har nu en test, der beviser, at det fejler på dårlige inddata, og områdeforventningerne læses fra sandhedskilden. Det ubehagelige er, hvad dette blotlagde: et grønt tjek havde været meningsløst mindst to steder i et ukendt tidsrum, og der er ingen måde at finde ud af med tilbagevirkende kraft, hvad der slap igennem.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Har flyttet hver brugervendt streng ud af Python og ind i et indholdstræ på 874 filer på tre sprog, efter at have fundet døde oversættelser, ingen kunne se var døde, og et tjek, der i stilhed bedømte en tredjedel af achievements.</title>
    <id>https://data.engineer.company/da/portfolio/moved-every-user-facing-string-into-a-content-tree-152/</id>
    <link href="https://data.engineer.company/da/portfolio/moved-every-user-facing-string-into-a-content-tree-152/" rel="alternate" type="text/html" />
    <updated>2026-09-13T15:01:29+02:00</updated>
    <published>2026-09-13T15:01:29+02:00</published>
    <category term="Backend‑udvikling" scheme="https://data.engineer.company/da/categories/" />
    <category term="Data governance" scheme="https://data.engineer.company/da/categories/" />
    <category term="Dokumentation" scheme="https://data.engineer.company/da/categories/" />
    <category term="Internationalisering" scheme="https://data.engineer.company/da/categories/" />
    <category term="Migrering &amp; modernisering" scheme="https://data.engineer.company/da/categories/" />
    <category term="Python" scheme="https://data.engineer.company/da/categories/" />
    <category term="Backend- &amp; API‑udvikling" scheme="https://data.engineer.company/da/services/" />
    <category term="Data governance &amp; datakvalitet" scheme="https://data.engineer.company/da/services/" />
    <category term="Databasemigrering &amp; modernisering" scheme="https://data.engineer.company/da/services/" />
    <category term="Internationalisering &amp; lokalisering" scheme="https://data.engineer.company/da/services/" />
    <summary>Prosaen kan nu redigeres uden at røre kode og sammenlignes på tværs af sprog ved at tælle. Prisen er, at tilføjelsen af et sprog nu er utvetydig frem for…</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Situation.&lt;/strong&gt; Hver brugervendt streng i generatoren — hver bedrift, hver anmeldelse, hver afsnitsoverskrift, hvert resumé, på tre sprog — lå inde i Python‑kildekode. Det gør redigeringen af en sætning til en kodeændring, gør gennemgangen af en oversættelse til en diff mod kildekode og gør det umuligt at se med et blik, om et sprog er komplet. Det skjuler også den fejltilstand, der betyder noget: en oversættelse kan være til stede, forkert og uopnåelig på samme tid.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Opgave.&lt;/strong&gt; Strengene skulle flyttes ud af koden og ind i et indholdstræ, der kan tælles, sammenlignes på tværs af sprog og tjekkes uden at køre gengiveren.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Handling.&lt;/strong&gt; Resultatet er 874 filer under en indholdsmappe, ordnet efter art og derefter efter sprog: bedrifter, anmeldelser, resuméer, titler, virksomheder, regioner, kategorier, ydelser, profiler, referencer og ansøgningsbrudstykker. Tabulatorseparerede filer, hvor enheden er en linje med en identifikator, enkeltfiler hvor enheden er et afsnit. Indlæseren læser dem ved bygningstid, og databasen samles ud fra dem, så træet er kilden og databasen er afledt. To fund kom direkte ud af at kunne tælle. Nogle oversatte strenge havde ikke længere nogen engelsk modpart — døde poster, som intet gengav, og som ingen kunne have bemærket, mens de var indlejret i kode, for en urefereret ordbogsnøgle ser præcis ud som en refereret. Og et indholdstjek, der skulle bedømme hver bedrift, læste kun den delmængde, det kunne opløse, bedømte syvogtredive ud af treoghalvfems og meldte succes. At gøre korpusset til en mappe gjorde begge dele synlige som en uoverensstemmelse i filtal.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Resultat.&lt;/strong&gt; Prosaen kan nu redigeres uden at røre kode og sammenlignes på tværs af sprog ved at tælle. Prisen er, at tilføjelsen af et sprog nu er utvetydig frem for gradvis — træet gør et ufuldstændigt sprog åbenlyst, hvilket er pointen, men det betyder også, at delvise oversættelser ikke kan udsendes stille, mens de færdiggøres.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Har bygget et tværsprogligt indholdstjek, der fejler, når en oversættelse taber et tal, det engelske angiver, og når et sprog bruger notation, det ikke bruger — og har fundet to danske beskrivelser, der manglede en metrik, og seksten ukrainske spænd, der citerede på engelsk vis.</title>
    <id>https://data.engineer.company/da/portfolio/built-a-cross-language-figure-and-notation-check-153/</id>
    <link href="https://data.engineer.company/da/portfolio/built-a-cross-language-figure-and-notation-check-153/" rel="alternate" type="text/html" />
    <updated>2026-09-13T15:01:29+02:00</updated>
    <published>2026-09-13T15:01:29+02:00</published>
    <category term="Automatisering &amp; CI/CD" scheme="https://data.engineer.company/da/categories/" />
    <category term="Data governance" scheme="https://data.engineer.company/da/categories/" />
    <category term="Dokumentation" scheme="https://data.engineer.company/da/categories/" />
    <category term="Internationalisering" scheme="https://data.engineer.company/da/categories/" />
    <category term="Python" scheme="https://data.engineer.company/da/categories/" />
    <category term="Test &amp; QA" scheme="https://data.engineer.company/da/categories/" />
    <category term="Data governance &amp; datakvalitet" scheme="https://data.engineer.company/da/services/" />
    <category term="Internationalisering &amp; lokalisering" scheme="https://data.engineer.company/da/services/" />
    <category term="Teknisk dokumentation" scheme="https://data.engineer.company/da/services/" />
    <summary>Atten reelle defekter lukket og klassen lukket med dem, da hver fremtidig oversættelse sammenlignes med sin engelske kilde, før den kan committes.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Situation.&lt;/strong&gt; Den mest skadelige slags oversættelsesfejl i et CV er ikke en kejtet vending. Det er et tal, der forsvinder. En engelsk sætning, der hævder en halvtredsindstyvedobbelt forbedring, oversat til en sætning, der siger &amp;ldquo;betydeligt&amp;rdquo;, er en påstand stille trukket tilbage på ét marked og fastholdt på et andet — og ingen stavekontrol, grammatikkontrol eller menneskelig læsning af målsproget alene vil nogensinde bemærke det, for den oversatte sætning er fuldkommen god prosa.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Opgave.&lt;/strong&gt; Der var brug for et tjek, som læser sprogene mod hinanden frem for hvert enkelt for sig, på de to ting, der skal overleve oversættelse: tallene og den notation, hvert sprog bruger til at skrive dem.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Handling.&lt;/strong&gt; Taltjekket udtrækker hvert tal, hver procentdel, hver multiplikator og hver enhed fra den engelske streng og kræver, at hver af dem optræder i hver oversættelse af den streng, med multiplikatorformerne kortlagt pr. sprog frem for matchet ordret — den engelske halvtredsindstyve‑gange‑form svarer til en bestemt dansk vending og en bestemt ukrainsk vending, og tjekket kender kortlægningen frem for at kræve cifrene alene. Notationstjekket er spejlbilledet af det: hvert sprog har konventioner, det skal bruge, og konventioner, det ikke må bruge, herunder decimalskilletegn, tusindgruppering og anførselstegn. Ukrainsk bruger vinkelanførselstegn; engelske dobbelte anførselstegn i en ukrainsk sætning er lige så forkerte som et manglende tal og langt lettere at indføre ved kopiering. Den første fulde kørsel fandt to danske beskrivelser, hvor et måltal til stede på engelsk var faldet ud, og seksten ukrainske spænd med anførsel i engelsk stil.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Resultat.&lt;/strong&gt; Atten reelle defekter lukket og klassen lukket med dem, da hver fremtidig oversættelse sammenlignes med sin engelske kilde, før den kan committes. Hvad tjekket ikke kan, er at bedømme mening: det beviser, at tallet overlevede, og at tegnsætningen er hjemmevant, og en oversættelse, der bevarer hvert tal, mens den vender påstanden om, består det uden videre.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Har auditeret 644 Rust‑crates for licenskompatibilitet ved hvert build og har bevist, at tjekket udløses, ved at omskrive én crates licens og ved at flytte den fastlåste kernerevision uden at regenerere.</title>
    <id>https://data.engineer.company/da/portfolio/audited-644-rust-crates-for-licence-compatibility-163/</id>
    <link href="https://data.engineer.company/da/portfolio/audited-644-rust-crates-for-licence-compatibility-163/" rel="alternate" type="text/html" />
    <updated>2026-09-13T15:01:29+02:00</updated>
    <published>2026-09-13T15:01:29+02:00</published>
    <category term="Automatisering &amp; CI/CD" scheme="https://data.engineer.company/da/categories/" />
    <category term="Data governance" scheme="https://data.engineer.company/da/categories/" />
    <category term="DevOps" scheme="https://data.engineer.company/da/categories/" />
    <category term="Dokumentation" scheme="https://data.engineer.company/da/categories/" />
    <category term="Sikkerhed" scheme="https://data.engineer.company/da/categories/" />
    <category term="Data governance &amp; datakvalitet" scheme="https://data.engineer.company/da/services/" />
    <category term="DevOps &amp; CI/CD‑automatisering" scheme="https://data.engineer.company/da/services/" />
    <category term="Sikkerhed &amp; adgangsstyring" scheme="https://data.engineer.company/da/services/" />
    <summary>Distributionspositionen tjekkes ved hver bygning, og tjekket vides at virke, fordi det blev bragt til at fejle, frem for fordi det aldrig har sagt noget.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Situation.&lt;/strong&gt; At sammenkæde en Rust‑kerne ind i et udsendt program betyder at udsende alt, den kerne afhænger af. Afhængighedsgrafen er 644 crates. Hver af dem bærer en licens, nogle bærer mere end én, og en enkelt copyleft‑crate, der ankommer tre niveauer nede gennem en rutinemæssig versionsopdatering, ændrer, hvad programmet som helhed må distribueres under — tavst, i en låsefil ingen læser linje for linje.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Opgave.&lt;/strong&gt; Licenspositionen skulle efterprøves ved hver bygning frem for gennemgås én gang, med en udtrykkelig tilladelsesliste, så en ændring i grafen er en bygningsfejl og ikke en opdagelse gjort senere af en anden.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Handling.&lt;/strong&gt; Revisionen opløser den fulde transitive graf og tjekker hver crates licensudtryk mod en liste over vilkår, projektet accepterer, og evaluerer de booleske udtryk korrekt — en crate, der tilbyder et valg mellem to licenser, er acceptabel, hvis en af dem står på listen, og en crate, der kræver begge, er kun acceptabel, hvis begge gør. Alt uden match fejler bygningen frem for at advare, og at føje et vilkår til tilladelseslisten er en bevidst redigering med en begrundelse. Et tjek, der aldrig har fejlet, kan ikke skelnes fra et, der ikke kan fejle, så det blev bragt til at fejle med vilje, to gange. Én gang ved at omskrive en crates licensudtryk til noget, listen ikke accepterer, hvilket er formen på en crate, der ændrer sine vilkår opstrøms mellem versioner — det tilfælde ingen menneskelig gennemgang fanger, fordi selve craten ikke er ny. Én gang ved at flytte den fastlåste kernerevision uden at genskabe revisionen, hvilket er formen på en kerneopdatering, der stille bringer en ny afhængighed med sig. Begge provokationer fejlede bygningen som tilsigtet, og tjekket blev efterladt på plads frem for udvidet.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Resultat.&lt;/strong&gt; Distributionspositionen tjekkes ved hver bygning, og tjekket vides at virke, fordi det blev bragt til at fejle, frem for fordi det aldrig har sagt noget. Før det fandtes, fremsatte pakken, licensfilen og projektets eget README alle en påstand om 644 crates, som intet havde efterprøvet. Begrænsningen er præcis og bør ikke overdrives: tjekket læser de erklærede licensmetadata, og metadata kan være forkerte eller ufuldstændige. Det beviser intet om en crate, der fejlerklærer sig selv, og det er ikke juridisk rådgivning.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Sådan åbner man en dApp i Solana-mobilwallets</title>
    <id>https://data.engineer.company/da/notes/solana-mobile-wallet-deeplinks/</id>
    <link href="https://data.engineer.company/da/notes/solana-mobile-wallet-deeplinks/" rel="alternate" type="text/html" />
    <updated>2026-09-13T15:01:29+02:00</updated>
    <published>2026-08-10T00:00:00Z</published>
    <summary>Hvorfor browse-deeplinks til Phantom, Solflare og Backpack fejler på mobilen — og de formater, regler og rettelser, der får dem til at virke.</summary>
    <content type="html">&lt;p&gt;En React-dApp bygget på &lt;code&gt;@solana/wallet-adapter-react&lt;/code&gt; forbinder&#xA;desktop-wallets uden problemer, men på en telefon falder det samme flow fra&#xA;hinanden: wallet&amp;rsquo;en skal åbne dApp&amp;rsquo;en i sin egen indbyggede browser, og de&#xA;deeplinks, der skulle klare det, virker bare ikke. Backpack lander på en &amp;ldquo;hent&#xA;appen&amp;rdquo;-side; Solflare åbner appen, men aldrig sitet; alle varianter ser ud til&#xA;at fejle. Vi skilte problemet ad, og det viste sig at være fire adskilte&#xA;problemer med ét fælles symptom.&lt;/p&gt;&#xA;&lt;h2 id=&#34;de-fire-problemer&#34;&gt;De fire problemer&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Backpack-linket var forkert bygget.&lt;/strong&gt; Det eneste dokumenterede format er&#xA;&lt;code&gt;https://backpack.app/ul/v1/browse/&amp;lt;url&amp;gt;?ref=&amp;lt;ref&amp;gt;&lt;/code&gt; — et universelt link med&#xA;mål-URL&amp;rsquo;en i stien og et påkrævet &lt;code&gt;ref&lt;/code&gt;. Et gæt med eget skema som&#xA;&lt;code&gt;backpack://ul/v1/browse?url=...&lt;/code&gt; matcher ingen rute i appen, så brugeren&#xA;ender på wallet&amp;rsquo;ens installationsside.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Solflare skal også bruge sit universelle link:&lt;/strong&gt;&#xA;&lt;code&gt;https://solflare.com/ul/v1/browse/&amp;lt;url&amp;gt;?ref=&amp;lt;ref&amp;gt;&lt;/code&gt; — ikke det rå&#xA;&lt;code&gt;solflare://&lt;/code&gt;-skema. Et råt skema kan starte appen uden at dirigere den —&#xA;hvilket er præcis &amp;ldquo;appen åbner, men site-fanen må åbnes med hånden&amp;rdquo;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Begge parametre skal være kodet.&lt;/strong&gt; &lt;code&gt;url&lt;/code&gt; er dApp&amp;rsquo;ens fulde absolutte&#xA;adresse, og &lt;code&gt;ref&lt;/code&gt; er den kaldende origin, hver især gennem&#xA;&lt;code&gt;encodeURIComponent&lt;/code&gt;. Et ukodet &lt;code&gt;?&lt;/code&gt; eller &lt;code&gt;&amp;amp;&lt;/code&gt; i målet ødelægger&#xA;fortolkningen, og wallet&amp;rsquo;en åbner på sin forside i stedet for browserfanen.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Udløsningen betyder lige så meget som linket.&lt;/strong&gt; Universelle links skifter&#xA;kun app ved en navigation, styresystemet stoler på — og de gør med vilje&#xA;ingenting, når de indsættes i adresselinjen, hvilket også er sådan, et helt&#xA;korrekt link &amp;ldquo;fejler&amp;rdquo; under test.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;de-dokumenterede-formater&#34;&gt;De dokumenterede formater&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Phantom: &lt;code&gt;https://phantom.app/ul/browse/&amp;lt;url&amp;gt;?ref=&amp;lt;ref&amp;gt;&lt;/code&gt; — uden &lt;code&gt;/v1&lt;/code&gt; i&#xA;netop dette.&lt;/li&gt;&#xA;&lt;li&gt;Solflare: &lt;code&gt;https://solflare.com/ul/v1/browse/&amp;lt;url&amp;gt;?ref=&amp;lt;ref&amp;gt;&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;Backpack: &lt;code&gt;https://backpack.app/ul/v1/browse/&amp;lt;url&amp;gt;?ref=&amp;lt;ref&amp;gt;&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Ét mønster dækker alle tre:&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;const WALLET_BROWSE = {&#xA;  phantom: (url, ref) =&amp;gt;&#xA;    `https://phantom.app/ul/browse/${url}?ref=${ref}`,&#xA;  solflare: (url, ref) =&amp;gt;&#xA;    `https://solflare.com/ul/v1/browse/${url}?ref=${ref}`,&#xA;  backpack: (url, ref) =&amp;gt;&#xA;    `https://backpack.app/ul/v1/browse/${url}?ref=${ref}`,&#xA;};&#xA;&#xA;function walletBrowseLink(&#xA;  walletName,&#xA;  targetUrl = window.location.href,&#xA;) {&#xA;  const build = WALLET_BROWSE[walletName.toLowerCase()];&#xA;  if (!build) return null;&#xA;  return build(&#xA;    encodeURIComponent(targetUrl),&#xA;    encodeURIComponent(window.location.origin),&#xA;  );&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;udløs-linket-så-ios-og-android-accepterer-det&#34;&gt;Udløs linket, så iOS og Android accepterer det&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Render et rigtigt anker, beregnet på forhånd.&lt;/strong&gt; Et almindeligt&#xA;&lt;code&gt;&amp;lt;a href={walletBrowseLink(&#39;phantom&#39;)}&amp;gt;&lt;/code&gt; er den mest pålidelige udløser på&#xA;begge platforme.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Skal det ske programmatisk&lt;/strong&gt;, så tildel &lt;code&gt;window.location.href&lt;/code&gt; synkront&#xA;inde i tryk-handleren — ingen &lt;code&gt;await&lt;/code&gt;, ingen &lt;code&gt;fetch&lt;/code&gt;, ingen &lt;code&gt;setTimeout&lt;/code&gt;&#xA;først. Efter asynkront arbejde er gestus-konteksten væk, og iOS falder&#xA;tilbage til wallet&amp;rsquo;ens websted. Aldrig &lt;code&gt;window.open&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Test aldrig ved at indsætte i adresselinjen.&lt;/strong&gt; Universelle links udløses&#xA;med vilje ikke dér; test med et link, der trykkes på, eller en QR-kode, som&#xA;kameraet scanner.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Pas på messenger-webviews.&lt;/strong&gt; Åbnet i Telegrams eller Instagrams indbyggede&#xA;browser bliver universelle links ofte slugt, og wallet&amp;rsquo;ens almindelige&#xA;websted indlæses i stedet. User-agent-detektion er i bedste fald et gæt, så&#xA;giv også brugerne en synlig nødudgang: &amp;ldquo;åbn i Safari eller Chrome, og&#xA;forbind derefter&amp;rdquo;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;den-større-løsning-på-android&#34;&gt;Den større løsning på Android&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Håndbyggede deeplinks er iOS-historien. På Android lader Solana Mobiles Mobile&#xA;Wallet Adapter en dApp i mobilbrowseren forbinde direkte til den installerede&#xA;wallet-app, helt uden omvejen om den indbyggede browser. Nyere versioner af&#xA;&lt;code&gt;@solana/wallet-adapter-react&lt;/code&gt; registrerer mobiladapteren automatisk, så en&#xA;opgradering af wallet-adapter-pakkerne kan løse Android alene. Målarkitekturen:&#xA;Mobile Wallet Adapter på Android, universelle browse-links på iOS, hvor Apple&#xA;ikke tillader en tilsvarende løsning.&lt;/p&gt;&#xA;&lt;h2 id=&#34;efterprøv-på-en-enhed&#34;&gt;Efterprøv på en enhed&lt;/h2&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Rigtig enhed, wallet installeret, link åbnet fra systembrowseren — ikke fra&#xA;en messenger.&lt;/li&gt;&#xA;&lt;li&gt;Tryk på et renderet link, eller scan en QR-kode; indsæt aldrig i&#xA;adresselinjen.&lt;/li&gt;&#xA;&lt;li&gt;Bekræft, at wallet&amp;rsquo;en åbner, og at dApp&amp;rsquo;en indlæses i dens indbyggede&#xA;browserfane — anden halvdel er den, der fejler.&lt;/li&gt;&#xA;&lt;li&gt;Gentag uden wallet&amp;rsquo;en installeret: det universelle link skal falde tilbage&#xA;til wallet&amp;rsquo;ens websted. Ser du dén side, mens appen er installeret, er&#xA;linket eller udløsningen stadig forkert.&lt;/li&gt;&#xA;&lt;li&gt;Test derefter messenger-vejen, og tilføj &amp;ldquo;åbn i browser&amp;rdquo;-hjælpen, hvis den&#xA;fejler dér.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;kilder&#34;&gt;Kilder&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://docs.phantom.com/phantom-deeplinks/deeplinks-ios-and-android&#34;&gt;Phantom: deeplinks på iOS og Android&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://docs.solflare.com/solflare/technical/deeplinks/other-methods/browse&#34;&gt;Solflare: Browse-deeplinket&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://docs.backpack.app/deeplinks/other-methods/browse&#34;&gt;Backpack: Browse-deeplinket&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://docs.solanamobile.com/mobile-wallet-adapter/mobile-apps&#34;&gt;Solana Mobile: Mobile Wallet Adapter&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</content>
  </entry>
</feed>
