Zum Hauptinhalt springen
tsecurity.de LIVE
Echtzeit-Radar & Feeds
Alle RSS Feeds
👥 Community & Social
Sichere ProgrammierungBreeze TTS 2 vs ElevenLabs: Open Source TTS Verdict(23.09.2026 um 05:44 Uhr)
Sichere ProgrammierungAgentic AI vs Generative AI: The 2026 Verdict(23.09.2026 um 05:44 Uhr)
Sichere ProgrammierungI made my agent prove every quote against the source document(23.09.2026 um 05:45 Uhr)
Sichere Programmierung8mb.video Alternative: Skip the Line, Skip the Upsell(23.09.2026 um 05:47 Uhr)
Sichere ProgrammierungBuilding a GTA 6 JSON API for entities and current status(23.09.2026 um 05:52 Uhr)
Sichere ProgrammierungEvery filter needs a documented exception(23.09.2026 um 06:01 Uhr)
Sichere ProgrammierungBreeze TTS 2 vs ElevenLabs: Open Source TTS Verdict(23.09.2026 um 05:44 Uhr)
Sichere ProgrammierungAgentic AI vs Generative AI: The 2026 Verdict(23.09.2026 um 05:44 Uhr)
Sichere ProgrammierungI made my agent prove every quote against the source document(23.09.2026 um 05:45 Uhr)
Sichere Programmierung8mb.video Alternative: Skip the Line, Skip the Upsell(23.09.2026 um 05:47 Uhr)
Sichere ProgrammierungBuilding a GTA 6 JSON API for entities and current status(23.09.2026 um 05:52 Uhr)
Sichere ProgrammierungEvery filter needs a documented exception(23.09.2026 um 06:01 Uhr)
Intelligence View
⚡ tsecurity.de Intelligence

My CI was green. At 150 connections, Postgres said no.

I built a small training log in Go called go-gym. Two front doors over one backend: a JSON API and a server-rendered HTMX UI. Nothing exotic. It had been sitting there with a green CI for weeks: build passes, tests pass, lint passes. Last…

0
↗ Quelle (dev.to)
Reagiere als Erste:r — dein Feedback zählt!

I built a small training log in Go called go-gym. Two front doors over one backend: a JSON API and a server-rendered HTMX UI. Nothing exotic. It had been sitting there with a green CI for weeks: build passes, tests pass, lint passes.



Last week I added a /metrics endpoint, got curious about the numbers behind it, and pointed a load generator at the dashboard to see the p95.



It didn't get slow. It fell over.



The setup was hey, 150 concurrent connections, 15 seconds, against GET /app. The dashboard is the heaviest read in the app: a stats aggregate, a page of workouts, and the activity heatmap counts. I expected mediocre latency. Instead the worst request took 13.5 seconds and a big chunk of them came back as errors.



The server log said why:




FATAL: sorry, too many clients already (SQLSTATE 53300)






Postgres was refusing connections. 321 of them across the run.



The part I'd never thought about was the database setup, which was one line:




db, err := sql.Open("pgx", dsn)






database/sql hands you a connection pool for free, and I'd been quietly assuming it was sensible out of the box. It isn't. SetMaxOpenConns defaults to zero, and zero means unlimited. So under load, every query that can't grab an idle connection just opens a new one. At 150 concurrent requests each running a few queries, the pool opened connection after connection until it walked straight into Postgres's max_connections, which is 100 by default. Past that, Postgres says no, and the handler returns a 500.



The /metrics endpoint I'd added the day before turned out to be useful, not as the thing under test but as the instrument. I could watch the latencies climb while the error rate went up. The bottleneck wasn't the query. It wasn't a missing index, which is what I'd have guessed if you woke me up and asked. It was that I was opening hundreds of connections to a server that wanted a hundred.



The fix is four lines:




db.SetMaxOpenConns(25)
db.SetMaxIdleConns(25)
db.SetConnMaxIdleTime(5 * time.Minute)
db.SetConnMaxLifetime(time.Hour)






25 sits well under Postgres's 100, with room to spare for migrations, a background job, and anything else holding a connection. The first line is the one that matters. Once the pool is capped, extra requests don't open new connections. They wait for one to free up. The queue moves to the client side, where waiting is cheap, instead of the database side, where it's fatal.



You might be reaching for the reply: just use pgxpool. Fair. Its native pool defaults to a bounded size, so it wouldn't have blown up this way out of the box. But the store and the migrations (goose) are both built on database/sql, so switching isn't free, and you'd still have to size the pool for your database either way. The point isn't which pool you pick. It's that you have to know its default and set the bound. database/sql just happens to ship the dangerous default.



Same load test after the change:


































GET /app, c=150, 15s
before after
failed requests 321 0
p95 latency requests were erroring out 32 ms
p99 latency 92 ms
throughput ~8,400 req/s


Before the fix, the worst request sat at 13.5 seconds before it gave up. After, the slowest 1% came back inside 92 milliseconds and nothing failed. One run, same machine, same dataset, so it's a clean comparison of the one thing I changed.



Let me be honest about what this is. It's hey on my laptop against a local Postgres with a small dataset, so the absolute numbers don't mean much. What's real is the failure mode. An unbounded pool will exhaust any connection-limited database the moment your concurrency is higher than the number of slots the database has, and it picks the worst possible time to do it, which is when you have traffic.



Two things stuck with me.



go build and my CI were green the entire time. Compiling tells you the types line up. It tells you nothing about what happens at 150 connections. The only reason I found this is that I ran the thing under load, which I did almost by accident.



And I would have guessed wrong. My reflex for "slow under load" is "add an index" or "there's an N+1 in there somewhere." The queries were fine. The pool was the problem, and I only knew that because the error said so, in plain words, in the log line up above. Measure the actual thing. Your instinct is a hypothesis, not an answer.



The four lines live in database.go, and there's a scripts/loadtest.sh in the repo if you want to reproduce the run. The whole project is at github.com/Aejkatappaja/go-gym. Set your pool limits. The default is a trap, and it stays quiet right up until it isn't.

Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten My CI was green. At 150 connections, Postgres said no.

Thematisch verwandte Begriffe: green, connections, Postgres, said · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Zum Aktualisieren ziehen
ZERO-DAY CVE-2026-18163 | IBM Financial Transaction Manager (FTM) for RedHat OpenShift could allow…
Advisory →
TTS Reader • tsecurity.de Voice
tsecurity.de Icon
tsecurity.de App
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag
Themen-Radar & Intelligence Matrix
Echtzeit-Taxonomie nach Angriffsvektoren & Plattformen

tsecurity.de Live Threat Radar

🔴 LIVE RADAR
MONITORING
AKTIV
CVE-DATENBANK
LIVE
🔍
Community Radar & Live Chat
Sentinel Bot online • Live-Stream
Dein Cluster: Security Explorer
Match:
lädt…
Verbindung zum Community-Stream wird aufgebaut...
Bearbeitungsmodus — Senden überschreibt deine Nachricht
Community-Puls — was gerade passiert
lädt…
Aktivitäten deiner Analysten
lädt…
Neues Thema oder Eilmeldung einreichen

Reiche interessante Links, Zero-Days oder Debatten ein. Die Community entscheidet per Upvote über die Veröffentlichung.

Heiß diskutierte Einreichungen
🔖 Gespeicherte Artikel
📂 Keine gespeicherten Artikel vorhanden.
Zurück Ziehen Vor
Links: vorheriger Artikel Rechts: nächster Artikel unten: schließen
News NIS-2 Frühwarnung Tier-1 Intel ⏱️ 3 Min vor 10 Min
Artikeldaten werden geladen...

Zurück: vorheriger Vor: nächster
↗ Original-Quelle
Social Reaktionen Deine Reaktion zählt
Einstufung & Relevanz-Poll 0 Stimmen
In sozialen Netzwerken teilen 1-Klick