Hoppa till innehåll
Fullstack & WebbPostgresDatabasFullstack-arkitektur14 min läsning

Postgres för SaaS-bolag: Partitioning, indexing och read replicas

Hur du får Postgres att hålla när tabellerna går från tusentals till miljontals rader.

18 februari 2026Uppdaterad 10:00
00
Postgres för SaaS-bolag: Partitioning, indexing och read replicas
De flesta prestandaproblem i Postgres löses med rätt index - inte med större hårdvara.Photo: Unsplash

Optimera Postgres för SaaS-skala. Partitioning, index och read replicas.

Postgres är förvånansvärt tålig. De flesta SaaS-bolag kan köra långt på en enkel instans utan att ens tänka på prestanda. Men någonstans mellan de första hundra kunderna och de första tusen brukar samma fråga som var snabb i fjol plötsligt ta sekunder, och då blir det bråttom. Den här texten handlar om de tre verktyg jag tar till i den ordningen: index först, sedan partitioning, och read replicas sist. Ordningen är viktig - de löser olika problem och har väldigt olika kostnad.

Index löser de flesta problem - om de är rätt

När en fråga blivit långsam är svaret nästan alltid ett index som saknas eller ett index som inte används. Det första jag gör är att titta på frågeplanen med EXPLAIN ANALYZE. En sekventiell skanning över en stor tabell där du filtrerar på en kolumn är en tydlig signal att ett index behövs. Men det räcker inte att lägga index slentrianmässigt - varje index kostar vid skrivning och tar plats.

Det jag ser oftast missas är sammansatta index i rätt ordning. Filtrerar du ofta på company_id och sorterar på datum, ska indexet täcka båda i den ordningen. Ett enda väl utformat sammansatt index slår tre separata. Den här typen av analys är ofta första steget när jag hjälper SaaS-bolag inom fullstack-arkitektur.

Partitioning för tabeller som bara växer

Vissa tabeller slutar aldrig att växa - händelseloggar, mätvärden, transaktioner. När en sådan tabell når tiotals miljoner rader börjar även indexerade frågor och underhåll bli tröga. Partitioning delar upp tabellen fysiskt, oftast på datum, så att en fråga om den senaste veckan bara rör den senaste partitionen istället för hela historiken. Det gör också att du kan radera gammal data genom att släppa en hel partition, vilket är oändligt mycket snabbare än att radera rader.

Men partitioning är inte gratis komplexitet. Den lönar sig först när tabellen verkligen är stor och frågorna har ett naturligt tidsfönster. Att partitionera en liten tabell är överengineering som bara gör schemat krångligare.

Read replicas: skala läsning, inte skrivning

När databasen är tungt belastad är frestelsen att lägga till en read replica och peka läsningar dit. Det fungerar utmärkt för rapporter, analyser och tunga läsningar som tål att vara någon sekund inaktuella. Men det är viktigt att förstå vad en replica inte löser: den hjälper inte mot skrivlast, och den introducerar replikeringsfördröjning. Läser du data direkt efter att du skrivit den kan du läsa en gammal version från replican.

Min regel: använd replicas för läsningar som tål eftersläpning - dashboards, exporter, sökning - och håll allt som måste vara omedelbart konsistent mot primären. Att blanda ihop det ger subtila buggar som är otäcka att felsöka.

Connection pooling innan du tror du behöver det

En sak som överraskar många: Postgres tål inte hur många samtidiga anslutningar som helst. En serverlös frontend som öppnar en anslutning per anrop kan slå i taket långt innan databasen är hårt belastad i övrigt. En connection pooler som PgBouncer löser det här, och i en serverlös arkitektur är det ofta nödvändigt från start, inte en optimering för senare.

Mät innan du gissar

Den röda tråden i allt det här: optimera aldrig på magkänsla. Slå på loggning av långsamma frågor, titta på vilka frågor som faktiskt kostar mest, och åtgärda dem i tur och ordning. Det är nästan alltid ett fåtal frågor som står för merparten av lasten. Hur en sådan systematisk genomgång ser ut visar jag i kundcase.

Relaterat

Vill du ta det vidare?

Jag hjälper SaaS-bolag att få Postgres att hålla när det skalar - rätt index, partitioning där det lönar sig och en plan för läsning kontra skrivning. Boka ett samtal så tittar vi på er databas.

Index först, partitioning sedan, read replicas sist. De löser olika problem och har väldigt olika kostnad - ta dem i rätt ordning.

- Simon Axelsson

Vanliga frågor

När bör vi börja med partitioning?
Först när en tabell verkligen är stor - tiotals miljoner rader och uppåt - och frågorna har ett naturligt tidsfönster som senaste veckan eller månaden. Att partitionera mindre tabeller adderar bara komplexitet utan vinst. Lös prestandaproblem med index så länge det räcker.
Löser en read replica vår databasbelastning?
Bara om belastningen är läsning. En replica avlastar tunga läsningar som rapporter och exporter men hjälper inte mot skrivlast och introducerar replikeringsfördröjning. Håll allt som måste vara omedelbart konsistent mot primären och skicka bara eftersläpningståliga läsningar till replican.
Varför får vi slut på databasanslutningar trots låg last?
Postgres har en relativt låg gräns för samtidiga anslutningar, och serverlösa miljöer som öppnar en anslutning per anrop slår i taket snabbt. En connection pooler som PgBouncer återanvänder anslutningar och är ofta nödvändig från start i serverlösa arkitekturer.

Om författaren

Simon Axelsson
Simon AxelssonIT-konsult & teknisk rådgivare

Simon Axelsson är senior IT-konsult och grundare av SIAX Technology AB. Han hjälper nordiska företag med molninfrastruktur, dataplattformar och AI-automation.

Fler artiklar av Simon