Does my channel buffer size choice hide backpressure problems, and how do I decide it?
Keep channel capacity near the worker count, let blocking propagate to the Kafka poll loop, and when consumer lag climbs grow workers, not the buffer.
Just Ask
Ask me anything about software architecture, careers, PHP, Go and the craft of building software; I answer here, in the open, for everyone.
Whatever’s on your mind, don’t hold back. Questions reach me directly; I answer the good ones and publish them on this page. Your email is never published.
Keep channel capacity near the worker count, let blocking propagate to the Kafka poll loop, and when consumer lag climbs grow workers, not the buffer.
With 3 stable types and a real need for foreign keys, use a single-table exclusive arc; if the type set is open-ended, go pure morph with a morph map.
Stay in FPM and start with a Guzzle Pool pinned to 20-50 concurrency; move to AMPHP v3 only if the codebase grows async, Swoole only when re-architecting.
Kill the reflex to grab the keyboard; your metric isn't how fast you ship today but whether the junior needs you a little less each week.
Start with RED on the API, model jobs as requests to run RED on the workers too, then layer USE onto both for queue depth and pool saturation.
Flip `CMD` to exec form and listen with `signal.NotifyContext(..., syscall.SIGTERM)` instead of `os.Interrupt`; add tini only if the worker forks.
Standardize on RFC 9457 rather than 7807, produce every error body in one central exception handler, and manage the `type` URI as a versionable contract.
Add `INCLUDE` only when the query is hot and `EXPLAIN (ANALYZE, BUFFERS)` shows heap access dominating, then tighten autovacuum until `Heap Fetches: 0`.
Move to `errgroup.WithContext` with a request-level timeout on top and thread ctx into every HTTP and DB call; an ignored ctx means no cancellation at all.
Use `chunkById()` when there is real per-row work and never touch the cursor column; if you only update a column, switch to one set-based `UPDATE`.