ワンクリックで
postgresql-review
PostgreSQL query review, optimalisering og beste praksis for Nav-applikasjoner
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
PostgreSQL query review, optimalisering og beste praksis for Nav-applikasjoner
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
| name | postgresql-review |
| description | PostgreSQL query review, optimalisering og beste praksis for Nav-applikasjoner |
| license | MIT |
| compatibility | PostgreSQL database |
| metadata | {"domain":"backend","tags":"postgresql sql optimization review indexing"} |
Review and optimize PostgreSQL queries, schemas, and patterns for Nav applications. Covers EXPLAIN analysis, index strategies, JSONB patterns, and common anti-patterns.
Run EXPLAIN (ANALYZE, BUFFERS, FORMAT TEXT) to analyze queries:
EXPLAIN (ANALYZE, BUFFERS, FORMAT TEXT)
SELECT * FROM vedtak
WHERE bruker_id = '12345678901'
AND status = 'aktiv'
ORDER BY opprettet_dato DESC
LIMIT 10;
| Sign | Problem | Solution |
|---|---|---|
Seq Scan on large table | Missing index | CREATE INDEX |
Sort with external merge | Not enough work_mem | Increase work_mem or add index with correct sort order |
Nested Loop with high rows | Cartesian product / missing join index | Add index on join column |
Hash Join with Batches > 1 | work_mem too low | Increase work_mem for the session |
Large difference between estimated and actual rows | Outdated statistics | ANALYZE tablename; |
-- Simple index for lookups
CREATE INDEX idx_vedtak_bruker_id ON vedtak(bruker_id);
-- Composite index — columns in order of selectivity
CREATE INDEX idx_vedtak_bruker_status ON vedtak(bruker_id, status);
-- Partial index — only relevant rows
CREATE INDEX idx_vedtak_aktive ON vedtak(bruker_id)
WHERE status = 'aktiv';
-- Covering index — avoids table lookup
CREATE INDEX idx_vedtak_covering ON vedtak(bruker_id, status)
INCLUDE (opprettet_dato, belop);
-- Concurrent — no table locking (requires outside transaction)
CREATE INDEX CONCURRENTLY idx_vedtak_dato ON vedtak(opprettet_dato);
| Scenario | Index Type |
|---|---|
WHERE a = x | B-tree on a |
WHERE a = x AND b = y | Composite (a, b) |
WHERE a = x AND status = 'aktiv' | Partial index WHERE status = 'aktiv' |
WHERE a LIKE 'prefix%' | B-tree (prefix only) |
WHERE a @> '{"key": "val"}' | GIN on JSONB |
| Full-text search | GIN with to_tsvector |
| Geography | GiST |
-- ✅ Correct — GIN index for JSONB queries
CREATE INDEX idx_metadata_gin ON hendelser USING GIN (metadata);
-- Query JSONB
SELECT * FROM hendelser
WHERE metadata @> '{"type": "vedtak", "tema": "dagpenger"}';
-- Fetch nested values
SELECT
id,
metadata->>'type' AS type,
metadata->'detaljer'->>'belop' AS belop
FROM hendelser;
-- ❌ Wrong — casting in WHERE without index
SELECT * FROM hendelser
WHERE (metadata->>'opprettet')::timestamp > NOW() - INTERVAL '7 days';
-- ✅ Better — use expression index
CREATE INDEX idx_metadata_opprettet ON hendelser (((metadata->>'opprettet')::timestamp));
-- ✅ Correct — CTE for readability
WITH aktive_vedtak AS (
SELECT bruker_id, COUNT(*) AS antall
FROM vedtak
WHERE status = 'aktiv'
GROUP BY bruker_id
),
siste_aktivitet AS (
SELECT bruker_id, MAX(opprettet_dato) AS sist_aktiv
FROM aktivitetslogg
GROUP BY bruker_id
)
SELECT
av.bruker_id,
av.antall,
sa.sist_aktiv
FROM aktive_vedtak av
JOIN siste_aktivitet sa USING (bruker_id)
WHERE av.antall > 1;
-- Ranking within group
SELECT
bruker_id,
vedtak_id,
opprettet_dato,
ROW_NUMBER() OVER (PARTITION BY bruker_id ORDER BY opprettet_dato DESC) AS rn
FROM vedtak
WHERE rn = 1; -- Latest vedtak per user
-- Running total
SELECT
dato,
antall,
SUM(antall) OVER (ORDER BY dato) AS kumulativt
FROM daglig_statistikk;
// ❌ Wrong — N+1: one query per user
val brukere = repository.findAll()
brukere.forEach { bruker ->
val vedtak = vedtakRepository.findByBrukerId(bruker.id) // N extra queries
}
// ✅ Correct — JOIN or batch query
val brukereOgVedtak = repository.findAllWithVedtak() // Single query with JOIN
-- ❌ Wrong — fetches all columns incl. large JSONB/TEXT
SELECT * FROM dokument WHERE bruker_id = '12345';
-- ✅ Correct — only necessary columns
SELECT id, tittel, opprettet_dato FROM dokument WHERE bruker_id = '12345';
-- ❌ Wrong — can return millions of rows
SELECT * FROM hendelse WHERE type = 'innlogging';
-- ✅ Correct — always limit result set
SELECT * FROM hendelse WHERE type = 'innlogging'
ORDER BY opprettet_dato DESC
LIMIT 100;
// HikariCP — recommended configuration for Nais
HikariDataSource().apply {
jdbcUrl = System.getenv("DB_JDBC_URL")
?: "jdbc:postgresql://${System.getenv("DB_HOST")}:5432/${System.getenv("DB_DATABASE")}"
username = System.getenv("DB_USERNAME")
password = System.getenv("DB_PASSWORD")
maximumPoolSize = 5 // Nais: start low, scale up as needed
minimumIdle = 1
connectionTimeout = 10_000
idleTimeout = 300_000
maxLifetime = 600_000
validationTimeout = 5_000
}
-- Add column with default (PostgreSQL 11+ — instant, no rewrite)
ALTER TABLE stor_tabell ADD COLUMN ny_kolonne BOOLEAN DEFAULT false;
-- Create index without locking the table
CREATE INDEX CONCURRENTLY idx_ny ON stor_tabell(ny_kolonne);
-- Batch update (avoid long transaction)
-- Run in application code with batches of 10,000 rows:
UPDATE stor_tabell SET ny_kolonne = true WHERE id BETWEEN $1 AND $2;
WHERE columns have indexes?EXPLAIN ANALYZE been run for new/changed queries?SELECT * in production code?LIMIT on queries that can return many rows?CONCURRENTLY?Generer conventional commit-meldinger med Nav-relevante scopes og breaking change-format
Expert builder for the Aksel design system (Nav / @navikt) React components, design tokens, layout primitives, theming (light/dark), icons, CSS, the Tailwind preset, version migrations, and Figma-to-code. Trigger on any frontend UI task that mentions Aksel, Nav/Navikt, "designsystemet", or @navikt/ds-* / @navikt/aksel-* packages — or that asks to add, create, build, or refactor a component (button, input, modal, table, alert, card, form) or layout, or to implement a design from Figma (a pasted figma.com/design/...?node-id link, "implement this design", "build this from Figma", design-to-code). Strong signals "using/with aksel", "@navikt/ds-react", "design system", a pasted figma.com link. If the work is frontend UI and there is any Aksel signal, invoke this skill unless the user explicitly opts out.
Integrer og konfigurer Nav Dekoratøren – felles header og footer for nav.no-applikasjoner. Bruk når et team skal ta i bruk Dekoratøren, oppdatere konfigurasjon, legge til breadcrumbs/språkvelger/analytics, håndtere samtykke (ekomloven), CSP eller feilsøke integrasjon mot dekoratøren.
Lag responsive layouts med Aksel Design System (v8+) - spacing tokens, layout primitives (Box, HStack, VStack, HGrid, Page, Bleed) og ResponsiveProp
Generer og kjør Playwright E2E-tester for webapplikasjoner med page objects, auth fixtures og tilgjengelighetstester
Kompakt output-stil som kutter fyllord og beholder teknisk substans — spar output-tokens uten å miste nøyaktighet.