<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Andy Dixon: Blog</title>
  <subtitle>Daily technical writing by Andy Dixon: Go and Rust internals, Linux and security how-tos, cryptography and UK privacy law, checked against source.</subtitle>
  <link href="https://dixon.cx/blog/feed.xml" rel="self" type="application/atom+xml"></link>
  <link href="https://dixon.cx/blog" rel="alternate" type="text/html"></link>
  <id>https://dixon.cx/blog</id>
  <updated>2026-09-21T19:39:13Z</updated>
  <author>
    <name>Andy Dixon</name>
    <uri>https://dixon.cx/</uri>
  </author>
  <rights>Copyright 2026 Andy Dixon</rights>
  <entry>
    <title>Go&#39;s ConstantTimeCompare Returns Early on Length Mismatch</title>
    <link href="https://dixon.cx/blog/go-constant-time-compare-length-leak.html" rel="alternate" type="text/html"></link>
    <id>https://dixon.cx/blog/go-constant-time-compare-length-leak.html</id>
    <published>2026-09-21T19:39:13Z</published>
    <updated>2026-09-21T19:39:13Z</updated>
    <summary>subtle.ConstantTimeCompare is constant time only for equal-length inputs. What the length shortcut leaks, when it matters, and a hash-first fix.</summary>
    <category term="Go"></category>
    <category term="go"></category>
    <category term="crypto-subtle"></category>
    <category term="constant-time"></category>
    <category term="timing-attack"></category>
    <category term="security"></category>
    <category term="cryptography"></category>
  </entry>
  <entry>
    <title>Go&#39;s database/sql Pool: SetConnMaxLifetime Behind a Firewall</title>
    <link href="https://dixon.cx/blog/go-database-sql-setconnmaxlifetime-firewall.html" rel="alternate" type="text/html"></link>
    <id>https://dixon.cx/blog/go-database-sql-setconnmaxlifetime-firewall.html</id>
    <published>2026-09-21T15:39:32Z</published>
    <updated>2026-09-21T15:39:32Z</updated>
    <summary>Why the first query after a quiet spell hangs or fails when a firewall forgets your connection, and how lifetime and idle limits in database/sql fix it.</summary>
    <category term="Go"></category>
    <category term="go"></category>
    <category term="database-sql"></category>
    <category term="connection-pooling"></category>
    <category term="firewall"></category>
    <category term="networking"></category>
    <category term="debugging"></category>
  </entry>
  <entry>
    <title>Go&#39;s crypto/rand.Text and rand.Read: Why Seeded Tokens Get Guessed</title>
    <link href="https://dixon.cx/blog/go-crypto-rand-text-read-guessable-tokens.html" rel="alternate" type="text/html"></link>
    <id>https://dixon.cx/blog/go-crypto-rand-text-read-guessable-tokens.html</id>
    <published>2026-09-21T11:39:34Z</published>
    <updated>2026-09-21T11:39:34Z</updated>
    <summary>Why session tokens built from Go&#39;s non-cryptographic rand package get guessed, and how crypto/rand.Text and rand.Read replace them in a few lines.</summary>
    <category term="Go"></category>
    <category term="go"></category>
    <category term="crypto-rand"></category>
    <category term="random-numbers"></category>
    <category term="tokens"></category>
    <category term="security"></category>
    <category term="cryptography"></category>
  </entry>
  <entry>
    <title>Go&#39;s context.WithoutCancel: Keeping Audit Logs Alive After the Request Dies</title>
    <link href="https://dixon.cx/blog/go-context-withoutcancel-audit-logs.html" rel="alternate" type="text/html"></link>
    <id>https://dixon.cx/blog/go-context-withoutcancel-audit-logs.html</id>
    <published>2026-09-21T03:39:29Z</published>
    <updated>2026-09-21T03:39:29Z</updated>
    <summary>A client hangs up mid-request and your audit row silently never gets written. How context.WithoutCancel fixes it, and the timeout and shutdown traps it creates.</summary>
    <category term="Go"></category>
    <category term="go"></category>
    <category term="context"></category>
    <category term="withoutcancel"></category>
    <category term="audit-logging"></category>
    <category term="net-http"></category>
    <category term="error-handling"></category>
  </entry>
  <entry>
    <title>Go&#39;s http.Client: When Redirects Strip Authorization</title>
    <link href="https://dixon.cx/blog/go-http-client-redirects-strip-authorization.html" rel="alternate" type="text/html"></link>
    <id>https://dixon.cx/blog/go-http-client-redirects-strip-authorization.html</id>
    <published>2026-09-20T23:41:41Z</published>
    <updated>2026-09-20T23:41:41Z</updated>
    <summary>Learn when Go forwards or strips Authorization on redirects, why subdomains and scheme changes surprise, and how to enforce a safer policy.</summary>
    <category term="Go"></category>
    <category term="go"></category>
    <category term="net-http"></category>
    <category term="redirects"></category>
    <category term="authorization"></category>
    <category term="security"></category>
    <category term="debugging"></category>
  </entry>
  <entry>
    <title>Go&#39;s http.Transport Idle Pool: Why MaxIdleConnsPerHost Is 2</title>
    <link href="https://dixon.cx/blog/go-http-transport-max-idle-conns-per-host.html" rel="alternate" type="text/html"></link>
    <id>https://dixon.cx/blog/go-http-transport-max-idle-conns-per-host.html</id>
    <published>2026-09-20T19:38:52Z</published>
    <updated>2026-09-20T19:38:52Z</updated>
    <summary>Why Go keeps only two idle connections per host, how bursty traffic to one API burns handshakes, and how to measure and fix it with httptrace.</summary>
    <category term="Go"></category>
    <category term="go"></category>
    <category term="net-http"></category>
    <category term="http-transport"></category>
    <category term="connection-pooling"></category>
    <category term="performance"></category>
    <category term="networking"></category>
  </entry>
  <entry>
    <title>Go&#39;s http.Request.Clone: Which Fields Get Copied, Which Are Shared</title>
    <link href="https://dixon.cx/blog/go-http-request-clone-shared-headers-body.html" rel="alternate" type="text/html"></link>
    <id>https://dixon.cx/blog/go-http-request-clone-shared-headers-body.html</id>
    <published>2026-09-20T15:38:59Z</published>
    <updated>2026-09-20T15:38:59Z</updated>
    <summary>Request.Clone deep-copies headers but shares the Body, while WithContext shares almost everything. Here is what that means for RoundTrippers and retry loops.</summary>
    <category term="Go"></category>
    <category term="go"></category>
    <category term="net-http"></category>
    <category term="http-request"></category>
    <category term="roundtripper"></category>
    <category term="middleware"></category>
    <category term="debugging"></category>
  </entry>
  <entry>
    <title>Go&#39;s ServeMux Method Patterns: Why You Get 405, Not 404</title>
    <link href="https://dixon.cx/blog/go-servemux-method-patterns-405-not-404.html" rel="alternate" type="text/html"></link>
    <id>https://dixon.cx/blog/go-servemux-method-patterns-405-not-404.html</id>
    <published>2026-09-20T11:39:19Z</published>
    <updated>2026-09-20T11:39:19Z</updated>
    <summary>Since Go 1.22, ServeMux returns 405 with an Allow header when a path matches a method pattern but the verb does not. Here is why, and what PathValue sees.</summary>
    <category term="Go"></category>
    <category term="go"></category>
    <category term="net-http"></category>
    <category term="servemux"></category>
    <category term="routing"></category>
    <category term="pathvalue"></category>
    <category term="debugging"></category>
  </entry>
  <entry>
    <title>Go&#39;s http.ResponseController: Resetting Streaming Deadlines</title>
    <link href="https://dixon.cx/blog/go-responsecontroller-resetting-streaming-deadlines.html" rel="alternate" type="text/html"></link>
    <id>https://dixon.cx/blog/go-responsecontroller-resetting-streaming-deadlines.html</id>
    <published>2026-09-20T03:41:35Z</published>
    <updated>2026-09-20T03:41:35Z</updated>
    <summary>Give each streamed chunk its own write deadline, surface flush errors promptly, and keep healthy long-lived HTTP responses alive in Go.</summary>
    <category term="Go"></category>
    <category term="go"></category>
    <category term="net-http"></category>
    <category term="responsecontroller"></category>
    <category term="streaming"></category>
    <category term="timeouts"></category>
    <category term="server-sent-events"></category>
  </entry>
  <entry>
    <title>Go&#39;s net.Dialer and Happy Eyeballs: Why Dual-Stack Connects Lag</title>
    <link href="https://dixon.cx/blog/go-net-dialer-happy-eyeballs-dual-stack-connect.html" rel="alternate" type="text/html"></link>
    <id>https://dixon.cx/blog/go-net-dialer-happy-eyeballs-dual-stack-connect.html</id>
    <published>2026-09-19T23:39:06Z</published>
    <updated>2026-09-19T23:39:06Z</updated>
    <summary>How net.Dialer races IPv6 against IPv4, what FallbackDelay and Timeout really do, and why a black-holed AAAA record costs you 300ms per new connection.</summary>
    <category term="Go"></category>
    <category term="go"></category>
    <category term="net-dialer"></category>
    <category term="happy-eyeballs"></category>
    <category term="ipv6"></category>
    <category term="networking"></category>
    <category term="performance"></category>
  </entry>
  <entry>
    <title>Go&#39;s http.Hijacker: Where Buffered Bytes Go After an Upgrade</title>
    <link href="https://dixon.cx/blog/go-http-hijacker-buffered-bytes-after-upgrade.html" rel="alternate" type="text/html"></link>
    <id>https://dixon.cx/blog/go-http-hijacker-buffered-bytes-after-upgrade.html</id>
    <published>2026-09-19T19:42:11Z</published>
    <updated>2026-09-19T19:42:11Z</updated>
    <summary>Learn why reading the raw connection after http.Hijacker can hide protocol bytes, and how to handle upgrades without stalls or reordering.</summary>
    <category term="Go"></category>
    <category term="go"></category>
    <category term="net-http"></category>
    <category term="http-hijacker"></category>
    <category term="protocol-upgrade"></category>
    <category term="bufio"></category>
    <category term="networking"></category>
  </entry>
  <entry>
    <title>Go&#39;s io.Pipe Has No Buffer: How a Stalled Reader Freezes Writes</title>
    <link href="https://dixon.cx/blog/go-io-pipe-no-buffer-stalled-reader-freezes-writes.html" rel="alternate" type="text/html"></link>
    <id>https://dixon.cx/blog/go-io-pipe-no-buffer-stalled-reader-freezes-writes.html</id>
    <published>2026-09-19T15:41:27Z</published>
    <updated>2026-09-19T15:41:27Z</updated>
    <summary>See why io.Pipe writes block, reproduce the freeze, and structure Go streaming pipelines so errors and cancellation unblock both ends.</summary>
    <category term="Go"></category>
    <category term="go"></category>
    <category term="io-pipe"></category>
    <category term="concurrency"></category>
    <category term="streaming"></category>
    <category term="goroutines"></category>
    <category term="debugging"></category>
  </entry>
  <entry>
    <title>Go&#39;s http.MaxBytesReader: Limiting Uploads Without Breaking Keep-Alive</title>
    <link href="https://dixon.cx/blog/go-http-maxbytesreader-uploads-keep-alive.html" rel="alternate" type="text/html"></link>
    <id>https://dixon.cx/blog/go-http-maxbytesreader-uploads-keep-alive.html</id>
    <published>2026-09-19T11:42:55Z</published>
    <updated>2026-09-19T11:42:55Z</updated>
    <summary>Use http.MaxBytesReader to cap Go uploads, return 413 reliably, and understand when HTTP/1.1 connections can safely stay alive.</summary>
    <category term="Go"></category>
    <category term="go"></category>
    <category term="net-http"></category>
    <category term="uploads"></category>
    <category term="keep-alive"></category>
    <category term="security"></category>
    <category term="error-handling"></category>
  </entry>
  <entry>
    <title>Go&#39;s os.Root: Traversal-Resistant File Access Without openat2</title>
    <link href="https://dixon.cx/blog/go-os-root-traversal-resistant-file-access.html" rel="alternate" type="text/html"></link>
    <id>https://dixon.cx/blog/go-os-root-traversal-resistant-file-access.html</id>
    <published>2026-09-19T03:39:02Z</published>
    <updated>2026-09-19T03:39:02Z</updated>
    <summary>Go 1.24&#39;s os.Root confines file access to a directory, symlinks and .. included. See how it works, a zip-extraction example, and what it does not cover.</summary>
    <category term="Go"></category>
    <category term="go"></category>
    <category term="os-root"></category>
    <category term="path-traversal"></category>
    <category term="security"></category>
    <category term="symlinks"></category>
    <category term="files"></category>
  </entry>
  <entry>
    <title>Go&#39;s sync.Pool: Why Pooled Buffers Leak Data Between Requests</title>
    <link href="https://dixon.cx/blog/go-sync-pool-buffers-leak-data-between-requests.html" rel="alternate" type="text/html"></link>
    <id>https://dixon.cx/blog/go-sync-pool-buffers-leak-data-between-requests.html</id>
    <published>2026-09-18T23:39:12Z</published>
    <updated>2026-09-18T23:39:12Z</updated>
    <summary>How sync.Pool buffers end up showing one request&#39;s bytes to another: missing resets, aliasing after Put, over-long slices, and stale secrets, with fixes.</summary>
    <category term="Go"></category>
    <category term="go"></category>
    <category term="sync-pool"></category>
    <category term="memory-safety"></category>
    <category term="security"></category>
    <category term="concurrency"></category>
    <category term="debugging"></category>
  </entry>
  <entry>
    <title>Go&#39;s net/netip vs net.IP: Why == Finally Works on Addresses</title>
    <link href="https://dixon.cx/blog/go-netip-vs-net-ip-comparing-addresses.html" rel="alternate" type="text/html"></link>
    <id>https://dixon.cx/blog/go-netip-vs-net-ip-comparing-addresses.html</id>
    <published>2026-09-18T19:38:54Z</published>
    <updated>2026-09-18T19:38:54Z</updated>
    <summary>net.IP is a byte slice, so == won&#39;t compile and map keys need string hacks. netip.Addr is a comparable value type; here are the sharp edges that remain.</summary>
    <category term="Go"></category>
    <category term="go"></category>
    <category term="netip"></category>
    <category term="net-ip"></category>
    <category term="networking"></category>
    <category term="maps"></category>
    <category term="ipv6"></category>
  </entry>
  <entry>
    <title>Go&#39;s exec.ErrDot: Why exec.Command Won&#39;t Run a Binary From PATH&#39;s Dot</title>
    <link href="https://dixon.cx/blog/go-os-exec-errdot-relative-path-lookup.html" rel="alternate" type="text/html"></link>
    <id>https://dixon.cx/blog/go-os-exec-errdot-relative-path-lookup.html</id>
    <published>2026-09-18T15:38:55Z</published>
    <updated>2026-09-18T15:38:55Z</updated>
    <summary>Since Go 1.19, os/exec refuses to run a program found via a relative PATH entry. What ErrDot means, why it exists, and the correct fixes.</summary>
    <category term="Go"></category>
    <category term="go"></category>
    <category term="os-exec"></category>
    <category term="path"></category>
    <category term="security"></category>
    <category term="errdot"></category>
    <category term="debugging"></category>
  </entry>
  <entry>
    <title>Signal&#39;s Double Ratchet in Go: A Toy Forward-Secret Messenger</title>
    <link href="https://dixon.cx/blog/signals-double-ratchet-in-go.html" rel="alternate" type="text/html"></link>
    <id>https://dixon.cx/blog/signals-double-ratchet-in-go.html</id>
    <published>2026-09-18T11:41:08Z</published>
    <updated>2026-09-18T11:41:08Z</updated>
    <summary>Build a working Double Ratchet in Go from crypto/ecdh, HMAC and AES-GCM alone, and see exactly where forward secrecy and post-compromise security come from.</summary>
    <category term="Cryptography"></category>
    <category term="go"></category>
    <category term="cryptography"></category>
    <category term="double-ratchet"></category>
    <category term="signal-protocol"></category>
    <category term="x25519"></category>
    <category term="forward-secrecy"></category>
  </entry>
  <entry>
    <title>Go&#39;s bufio.Scanner Stops at 64 KiB: Reading Long Lines Safely</title>
    <link href="https://dixon.cx/blog/go-bufio-scanner-64-kib-long-lines.html" rel="alternate" type="text/html"></link>
    <id>https://dixon.cx/blog/go-bufio-scanner-64-kib-long-lines.html</id>
    <published>2026-09-18T03:42:27Z</published>
    <updated>2026-09-18T03:42:27Z</updated>
    <summary>Learn why Go&#39;s bufio.Scanner rejects long lines, when to raise its buffer limit, and how to read bounded records without risking runaway memory use.</summary>
    <category term="Go"></category>
    <category term="go"></category>
    <category term="bufio"></category>
    <category term="scanner"></category>
    <category term="io"></category>
    <category term="error-handling"></category>
    <category term="security"></category>
  </entry>
  <entry>
    <title>Right to Repair Meets Firmware Locks: What the UK&#39;s New Ecodesign Rules Actually Require</title>
    <link href="https://dixon.cx/blog/right-to-repair-firmware-locks-uk-ecodesign-rules.html" rel="alternate" type="text/html"></link>
    <id>https://dixon.cx/blog/right-to-repair-firmware-locks-uk-ecodesign-rules.html</id>
    <published>2026-09-17T23:44:34Z</published>
    <updated>2026-09-17T23:44:34Z</updated>
    <summary>The UK&#39;s 2021 right to repair rules cover washing machines and TVs, not phones: the ban on firmware-locked spare parts is still years away in Great Britain.</summary>
    <category term="UK Law"></category>
    <category term="uk-law"></category>
    <category term="right-to-repair"></category>
    <category term="ecodesign"></category>
    <category term="firmware"></category>
    <category term="consumer-protection"></category>
    <category term="product-safety"></category>
  </entry>
  <entry>
    <title>ESP8266 vs ESP32 for a Battery Sensor: Why the Older, Slower Chip Still Wins on Idle Current</title>
    <link href="https://dixon.cx/blog/esp8266-vs-esp32-battery-sensor-idle-current.html" rel="alternate" type="text/html"></link>
    <id>https://dixon.cx/blog/esp8266-vs-esp32-battery-sensor-idle-current.html</id>
    <published>2026-09-17T19:40:35Z</published>
    <updated>2026-09-17T19:40:35Z</updated>
    <summary>Deep sleep numbers suggest the ESP32 should be the more efficient chip, but RTC power domains and default configuration often leave it drawing more current.</summary>
    <category term="Embedded"></category>
    <category term="esp32"></category>
    <category term="esp8266"></category>
    <category term="embedded"></category>
    <category term="low-power"></category>
    <category term="battery"></category>
    <category term="iot"></category>
  </entry>
  <entry>
    <title>Go&#39;s singleflight: Stop Cache Misses Stampeding the Database</title>
    <link href="https://dixon.cx/blog/go-singleflight-stop-cache-misses-stampeding-database.html" rel="alternate" type="text/html"></link>
    <id>https://dixon.cx/blog/go-singleflight-stop-cache-misses-stampeding-database.html</id>
    <published>2026-09-17T15:41:58Z</published>
    <updated>2026-09-17T15:41:58Z</updated>
    <summary>Use singleflight to collapse concurrent cache misses, handle cancellation safely, and avoid subtle duplicate database reads in Go services.</summary>
    <category term="Go"></category>
    <category term="go"></category>
    <category term="singleflight"></category>
    <category term="caching"></category>
    <category term="concurrency"></category>
    <category term="database"></category>
    <category term="performance"></category>
  </entry>
  <entry>
    <title>Go&#39;s log/slog: Structured Logging Without Reaching for a Third-Party Logger</title>
    <link href="https://dixon.cx/blog/go-slog-structured-logging.html" rel="alternate" type="text/html"></link>
    <id>https://dixon.cx/blog/go-slog-structured-logging.html</id>
    <published>2026-09-17T03:39:30Z</published>
    <updated>2026-09-17T03:39:30Z</updated>
    <summary>How Go&#39;s log/slog package gives you structured, leveled logging with context propagation, without adding zap or zerolog to go.mod.</summary>
    <category term="Go"></category>
    <category term="go"></category>
    <category term="slog"></category>
    <category term="structured-logging"></category>
    <category term="logging"></category>
    <category term="context"></category>
    <category term="observability"></category>
  </entry>
  <entry>
    <title>Go&#39;s GOMEMLIMIT: Keeping the OOM Killer Away From a Container</title>
    <link href="https://dixon.cx/blog/go-gomemlimit-oom-killer-containers.html" rel="alternate" type="text/html"></link>
    <id>https://dixon.cx/blog/go-gomemlimit-oom-killer-containers.html</id>
    <published>2026-09-16T23:40:07Z</published>
    <updated>2026-09-16T23:40:07Z</updated>
    <summary>Why a Go service can be OOM-killed inside a memory-limited container despite having a garbage collector, and how GOMEMLIMIT fixes the pacing.</summary>
    <category term="Go"></category>
    <category term="go"></category>
    <category term="gomemlimit"></category>
    <category term="garbage-collection"></category>
    <category term="containers"></category>
    <category term="kubernetes"></category>
    <category term="cgroups"></category>
  </entry>
  <entry>
    <title>Digital Forensics 101: Why dd and a Hash Beat cp When Imaging a Drive</title>
    <link href="https://dixon.cx/blog/forensic-disk-imaging-dd-vs-cp.html" rel="alternate" type="text/html"></link>
    <id>https://dixon.cx/blog/forensic-disk-imaging-dd-vs-cp.html</id>
    <published>2026-09-16T19:39:25Z</published>
    <updated>2026-09-16T19:39:25Z</updated>
    <summary>Why bit-for-bit disk imaging with dd, a write blocker and a SHA-256 checksum beats a filesystem copy when acquiring a drive for forensic analysis.</summary>
    <category term="Security"></category>
    <category term="forensics"></category>
    <category term="dd"></category>
    <category term="disk-imaging"></category>
    <category term="sha256"></category>
    <category term="chain-of-custody"></category>
    <category term="linux"></category>
  </entry>
  <entry>
    <title>Go&#39;s io.Copy Can Write Gigabytes Before Reporting an Error</title>
    <link href="https://dixon.cx/blog/go-io-copy-partial-writes-errors.html" rel="alternate" type="text/html"></link>
    <id>https://dixon.cx/blog/go-io-copy-partial-writes-errors.html</id>
    <published>2026-09-16T15:41:30Z</published>
    <updated>2026-09-16T15:41:30Z</updated>
    <summary>Learn why io.Copy can partially mutate a destination before failing, how its byte count helps, and when to stage writes for an atomic result.</summary>
    <category term="Go"></category>
    <category term="go"></category>
    <category term="io-copy"></category>
    <category term="error-handling"></category>
    <category term="files"></category>
    <category term="streaming"></category>
    <category term="debugging"></category>
  </entry>
  <entry>
    <title>TOTP From Scratch in Go: Implementing RFC 6238 Without a Library</title>
    <link href="https://dixon.cx/blog/totp-from-scratch-in-go-rfc6238.html" rel="alternate" type="text/html"></link>
    <id>https://dixon.cx/blog/totp-from-scratch-in-go-rfc6238.html</id>
    <published>2026-09-16T03:39:49Z</published>
    <updated>2026-09-16T03:39:49Z</updated>
    <summary>How the six digits in your authenticator app are actually produced: HMAC-SHA1, dynamic truncation and time steps, built in plain Go.</summary>
    <category term="Cryptography"></category>
    <category term="go"></category>
    <category term="totp"></category>
    <category term="hotp"></category>
    <category term="rfc6238"></category>
    <category term="hmac-sha1"></category>
    <category term="mfa"></category>
  </entry>
  <entry>
    <title>OAuth 2.0 Device Authorization Grant: How CLI Tools Log In Without a Browser Redirect</title>
    <link href="https://dixon.cx/blog/oauth-device-authorization-grant-cli-login.html" rel="alternate" type="text/html"></link>
    <id>https://dixon.cx/blog/oauth-device-authorization-grant-cli-login.html</id>
    <published>2026-09-15T23:39:35Z</published>
    <updated>2026-09-15T23:39:35Z</updated>
    <summary>RFC 8628 explained: how tools like gh, docker and kubectl authenticate on headless machines by polling a token endpoint instead of a browser redirect.</summary>
    <category term="Security"></category>
    <category term="oauth2"></category>
    <category term="device-authorization-grant"></category>
    <category term="rfc8628"></category>
    <category term="cli"></category>
    <category term="authentication"></category>
    <category term="go"></category>
  </entry>
  <entry>
    <title>Go&#39;s errgroup: Cancelling Goroutines Without Reinventing sync.WaitGroup</title>
    <link href="https://dixon.cx/blog/go-errgroup-cancelling-goroutines.html" rel="alternate" type="text/html"></link>
    <id>https://dixon.cx/blog/go-errgroup-cancelling-goroutines.html</id>
    <published>2026-09-15T19:39:26Z</published>
    <updated>2026-09-15T19:39:26Z</updated>
    <summary>How golang.org/x/sync/errgroup collects errors, cancels sibling goroutines on first failure, and bounds concurrency without a semaphore channel.</summary>
    <category term="Go"></category>
    <category term="go"></category>
    <category term="errgroup"></category>
    <category term="concurrency"></category>
    <category term="goroutines"></category>
    <category term="context"></category>
    <category term="sync-waitgroup"></category>
  </entry>
  <entry>
    <title>Go&#39;s errors.Join: Combining Errors Without Losing errors.Is</title>
    <link href="https://dixon.cx/blog/go-errors-join-combining-errors.html" rel="alternate" type="text/html"></link>
    <id>https://dixon.cx/blog/go-errors-join-combining-errors.html</id>
    <published>2026-09-15T17:22:11Z</published>
    <updated>2026-09-15T17:22:11Z</updated>
    <summary>How errors.Join builds a tree of errors that still works with errors.Is and errors.As, and where the abstraction leaks.</summary>
    <category term="Go"></category>
    <category term="go"></category>
    <category term="error-handling"></category>
    <category term="errors-join"></category>
    <category term="errors-is"></category>
    <category term="multierror"></category>
    <category term="debugging"></category>
  </entry>
  <entry>
    <title>DKIM, SPF and DMARC for Self-Hosted Mail: A Practical Setup</title>
    <link href="https://dixon.cx/blog/dkim-spf-dmarc-self-hosted-mail.html" rel="alternate" type="text/html"></link>
    <id>https://dixon.cx/blog/dkim-spf-dmarc-self-hosted-mail.html</id>
    <published>2026-09-15T12:25:10Z</published>
    <updated>2026-09-15T12:25:10Z</updated>
    <summary>A step-by-step guide to configuring SPF, DKIM and DMARC for a self-hosted mail server, and why the DNS records alone will not stop spam folders.</summary>
    <category term="Security"></category>
    <category term="spf"></category>
    <category term="dkim"></category>
    <category term="dmarc"></category>
    <category term="email"></category>
    <category term="postfix"></category>
    <category term="self-hosting"></category>
  </entry>
  <entry>
    <title>Shamir&#39;s Secret Sharing in Go: Splitting a Key So No Single Person Holds It</title>
    <link href="https://dixon.cx/blog/shamirs-secret-sharing-in-go.html" rel="alternate" type="text/html"></link>
    <id>https://dixon.cx/blog/shamirs-secret-sharing-in-go.html</id>
    <published>2026-09-15T11:42:55Z</published>
    <updated>2026-09-15T11:42:55Z</updated>
    <summary>How Shamir&#39;s Secret Sharing splits a key into shares using polynomial interpolation over GF(256), with a working Go implementation.</summary>
    <category term="Cryptography"></category>
    <category term="go"></category>
    <category term="cryptography"></category>
    <category term="secret-sharing"></category>
    <category term="key-management"></category>
    <category term="finite-fields"></category>
    <category term="threshold-cryptography"></category>
  </entry>
  <entry>
    <title>Age Verification Under the Online Safety Act: What &#39;Highly Effective&#39; Actually Means in Practice</title>
    <link href="https://dixon.cx/blog/age-verification-online-safety-act-highly-effective.html" rel="alternate" type="text/html"></link>
    <id>https://dixon.cx/blog/age-verification-online-safety-act-highly-effective.html</id>
    <published>2026-09-15T03:40:40Z</published>
    <updated>2026-09-15T03:40:40Z</updated>
    <summary>Ofcom&#39;s &#39;highly effective&#39; age assurance rests on four criteria, not a fixed toolset, and 2026 enforcement shows what that means for real services.</summary>
    <category term="Privacy Law"></category>
    <category term="uk-law"></category>
    <category term="online-safety-act"></category>
    <category term="age-verification"></category>
    <category term="ofcom"></category>
    <category term="privacy"></category>
    <category term="ico"></category>
  </entry>
  <entry>
    <title>Encrypted Client Hello: The TLS Extension That Finally Hides Which Site You&#39;re Visiting</title>
    <link href="https://dixon.cx/blog/encrypted-client-hello-tls-sni-privacy.html" rel="alternate" type="text/html"></link>
    <id>https://dixon.cx/blog/encrypted-client-hello-tls-sni-privacy.html</id>
    <published>2026-09-14T23:42:01Z</published>
    <updated>2026-09-14T23:42:01Z</updated>
    <summary>TLS 1.3 still leaks the hostname you&#39;re connecting to in plaintext. Here&#39;s how Encrypted Client Hello fixes that, and where it still falls short.</summary>
    <category term="Security"></category>
    <category term="tls"></category>
    <category term="ech"></category>
    <category term="sni"></category>
    <category term="encryption"></category>
    <category term="networking"></category>
    <category term="privacy"></category>
  </entry>
  <entry>
    <title>seccomp-bpf in Go: Restricting Syscalls Without a Container</title>
    <link href="https://dixon.cx/blog/seccomp-bpf-go-restricting-syscalls-without-a-container.html" rel="alternate" type="text/html"></link>
    <id>https://dixon.cx/blog/seccomp-bpf-go-restricting-syscalls-without-a-container.html</id>
    <published>2026-09-14T19:41:29Z</published>
    <updated>2026-09-14T19:41:29Z</updated>
    <summary>How to build and install a seccomp-bpf syscall filter from a plain Go binary with golang.org/x/net/bpf, and why goroutines need the TSYNC flag.</summary>
    <category term="Systems Programming"></category>
    <category term="go"></category>
    <category term="seccomp"></category>
    <category term="linux"></category>
    <category term="security"></category>
    <category term="bpf"></category>
    <category term="syscalls"></category>
  </entry>
  <entry>
    <title>The UK-US Data Bridge: Where GDPR Adequacy Actually Stands in 2026</title>
    <link href="https://dixon.cx/blog/uk-us-data-bridge-gdpr-adequacy-2026.html" rel="alternate" type="text/html"></link>
    <id>https://dixon.cx/blog/uk-us-data-bridge-gdpr-adequacy-2026.html</id>
    <published>2026-09-14T15:42:48Z</published>
    <updated>2026-09-14T15:42:48Z</updated>
    <summary>A status check on the UK-US Data Bridge: PCLOB&#39;s quorum collapse, the Latombe appeal at the CJEU, and the UK&#39;s own EU adequacy renewal.</summary>
    <category term="Privacy Law"></category>
    <category term="uk-law"></category>
    <category term="gdpr"></category>
    <category term="data-protection"></category>
    <category term="data-privacy-framework"></category>
    <category term="privacy"></category>
    <category term="ico"></category>
  </entry>
  <entry>
    <title>Go&#39;s testing/synctest: Testing Concurrent Code Without Sleeping in Tests</title>
    <link href="https://dixon.cx/blog/go-synctest-testing-concurrent-code.html" rel="alternate" type="text/html"></link>
    <id>https://dixon.cx/blog/go-synctest-testing-concurrent-code.html</id>
    <published>2026-09-14T11:40:51Z</published>
    <updated>2026-09-14T11:40:51Z</updated>
    <summary>How Go 1.25&#39;s testing/synctest package lets you test timers, retries and debounce logic deterministically, without real time.Sleep calls.</summary>
    <category term="Go"></category>
    <category term="go"></category>
    <category term="testing"></category>
    <category term="synctest"></category>
    <category term="concurrency"></category>
    <category term="goroutines"></category>
    <category term="timers"></category>
  </entry>
  <entry>
    <title>Go&#39;s rate.Limiter: Token Buckets Explained by Reading the Source</title>
    <link href="https://dixon.cx/blog/go-rate-limiter-token-buckets-source.html" rel="alternate" type="text/html"></link>
    <id>https://dixon.cx/blog/go-rate-limiter-token-buckets-source.html</id>
    <published>2026-09-14T03:40:19Z</published>
    <updated>2026-09-14T03:40:19Z</updated>
    <summary>A walk through golang.org/x/time/rate&#39;s actual source to see how Go&#39;s token bucket limiter tracks tokens without a background goroutine.</summary>
    <category term="Go"></category>
    <category term="go"></category>
    <category term="rate-limiting"></category>
    <category term="token-bucket"></category>
    <category term="concurrency"></category>
    <category term="golang-x-time"></category>
    <category term="networking"></category>
  </entry>
  <entry>
    <title>Linux pidfds: Closing the PID Reuse Race in Supervisors</title>
    <link href="https://dixon.cx/blog/linux-pidfds-closing-pid-reuse-race.html" rel="alternate" type="text/html"></link>
    <id>https://dixon.cx/blog/linux-pidfds-closing-pid-reuse-race.html</id>
    <published>2026-09-13T23:42:01Z</published>
    <updated>2026-09-13T23:42:01Z</updated>
    <summary>Learn how Linux pidfds provide a stable handle for polling, signalling and waiting without accidentally targeting a reused PID.</summary>
    <category term="Systems Programming"></category>
    <category term="linux"></category>
    <category term="pidfd"></category>
    <category term="process-supervision"></category>
    <category term="signals"></category>
    <category term="epoll"></category>
    <category term="systems-programming"></category>
  </entry>
  <entry>
    <title>Go&#39;s comparable Constraint: Why a Struct with a Slice Field Can&#39;t Satisfy It</title>
    <link href="https://dixon.cx/blog/go-comparable-constraint-slice-field.html" rel="alternate" type="text/html"></link>
    <id>https://dixon.cx/blog/go-comparable-constraint-slice-field.html</id>
    <published>2026-09-13T19:39:23Z</published>
    <updated>2026-09-13T19:39:23Z</updated>
    <summary>Why Go&#39;s generics compiler rejects structs containing slices as comparable, the reasoning behind it, and how to work around it.</summary>
    <category term="Go"></category>
    <category term="go"></category>
    <category term="generics"></category>
    <category term="comparable"></category>
    <category term="slices"></category>
    <category term="type-constraints"></category>
    <category term="maps"></category>
  </entry>
  <entry>
    <title>Right to Erasure vs Backups: What UK GDPR Actually Requires</title>
    <link href="https://dixon.cx/blog/right-to-erasure-vs-backups-uk-gdpr.html" rel="alternate" type="text/html"></link>
    <id>https://dixon.cx/blog/right-to-erasure-vs-backups-uk-gdpr.html</id>
    <published>2026-09-13T15:40:39Z</published>
    <updated>2026-09-13T15:40:39Z</updated>
    <summary>Why UK GDPR&#39;s right to erasure doesn&#39;t mean scrubbing every backup tape immediately, and what the ICO actually expects organisations to do instead.</summary>
    <category term="Privacy Law"></category>
    <category term="uk-law"></category>
    <category term="gdpr"></category>
    <category term="data-protection"></category>
    <category term="backups"></category>
    <category term="privacy"></category>
    <category term="ico"></category>
  </entry>
  <entry>
    <title>What &#39;Authorisation&#39; Actually Means Under the Computer Misuse Act</title>
    <link href="https://dixon.cx/blog/computer-misuse-act-penetration-testing-authorisation.html" rel="alternate" type="text/html"></link>
    <id>https://dixon.cx/blog/computer-misuse-act-penetration-testing-authorisation.html</id>
    <published>2026-09-13T11:39:55Z</published>
    <updated>2026-09-13T11:39:55Z</updated>
    <summary>The Computer Misuse Act has no good-faith defence, so a pentest&#39;s legality rests entirely on paperwork. Here&#39;s what that paperwork actually needs to say.</summary>
    <category term="Privacy Law"></category>
    <category term="uk-law"></category>
    <category term="computer-misuse-act"></category>
    <category term="penetration-testing"></category>
    <category term="security"></category>
    <category term="privacy"></category>
    <category term="ico"></category>
  </entry>
  <entry>
    <title>Go&#39;s sync.Map: When It Actually Beats a Mutex-Protected Map</title>
    <link href="https://dixon.cx/blog/sync-map-vs-mutex-map-go.html" rel="alternate" type="text/html"></link>
    <id>https://dixon.cx/blog/sync-map-vs-mutex-map-go.html</id>
    <published>2026-09-13T03:40:51Z</published>
    <updated>2026-09-13T03:40:51Z</updated>
    <summary>Why sync.Map only wins for two specific access patterns, how Go 1.24&#39;s trie-based rewrite changed the numbers, and when a plain mutex wins instead.</summary>
    <category term="Go"></category>
    <category term="go"></category>
    <category term="sync-map"></category>
    <category term="concurrency"></category>
    <category term="mutex"></category>
    <category term="performance"></category>
    <category term="benchmarking"></category>
  </entry>
  <entry>
    <title>ESP32 Deep Sleep Power Budgeting: Why &#39;Low Power&#39; Mode Still Drains a Battery in Days</title>
    <link href="https://dixon.cx/blog/esp32-deep-sleep-power-budgeting.html" rel="alternate" type="text/html"></link>
    <id>https://dixon.cx/blog/esp32-deep-sleep-power-budgeting.html</id>
    <published>2026-09-12T23:39:30Z</published>
    <updated>2026-09-12T23:39:30Z</updated>
    <summary>Deep sleep current specs look great on paper, but wake-up current spikes and a board&#39;s regulator usually decide the real battery life.</summary>
    <category term="Embedded"></category>
    <category term="esp32"></category>
    <category term="embedded"></category>
    <category term="low-power"></category>
    <category term="battery"></category>
    <category term="iot"></category>
    <category term="power-management"></category>
  </entry>
  <entry>
    <title>Postgres Advisory Locks in Go: Cheaper Than a Distributed Lock Service</title>
    <link href="https://dixon.cx/blog/postgres-advisory-locks-go.html" rel="alternate" type="text/html"></link>
    <id>https://dixon.cx/blog/postgres-advisory-locks-go.html</id>
    <published>2026-09-12T19:39:52Z</published>
    <updated>2026-09-12T19:39:52Z</updated>
    <summary>How to use Postgres advisory locks from Go for cron dedup and leader election, and the connection-pooling pitfall that breaks them silently.</summary>
    <category term="Go"></category>
    <category term="go"></category>
    <category term="postgresql"></category>
    <category term="distributed-locks"></category>
    <category term="pgx"></category>
    <category term="concurrency"></category>
    <category term="database"></category>
  </entry>
  <entry>
    <title>Hybrid Post-Quantum TLS 1.3: Why ML-KEM Rides Alongside ECDHE</title>
    <link href="https://dixon.cx/blog/hybrid-post-quantum-tls-mlkem-ecdhe.html" rel="alternate" type="text/html"></link>
    <id>https://dixon.cx/blog/hybrid-post-quantum-tls-mlkem-ecdhe.html</id>
    <published>2026-09-12T15:40:54Z</published>
    <updated>2026-09-12T15:40:54Z</updated>
    <summary>Why TLS 1.3&#39;s post-quantum key exchange combines ML-KEM with ECDHE instead of replacing it, and what that costs in handshake size.</summary>
    <category term="Cryptography"></category>
    <category term="tls"></category>
    <category term="post-quantum-cryptography"></category>
    <category term="ml-kem"></category>
    <category term="ecdhe"></category>
    <category term="key-exchange"></category>
    <category term="go"></category>
  </entry>
  <entry>
    <title>Rural Broadband and CGNAT: Why Self-Hosting Needs a Reverse Tunnel</title>
    <link href="https://dixon.cx/blog/rural-broadband-cgnat-reverse-tunnel.html" rel="alternate" type="text/html"></link>
    <id>https://dixon.cx/blog/rural-broadband-cgnat-reverse-tunnel.html</id>
    <published>2026-09-12T03:31:23Z</published>
    <updated>2026-09-12T03:31:23Z</updated>
    <summary>Starlink and most 4G home routers hide you behind CGNAT, so port forwarding does nothing. Here&#39;s how a reverse WireGuard tunnel fixes it.</summary>
    <category term="Systems Programming"></category>
    <category term="cgnat"></category>
    <category term="wireguard"></category>
    <category term="starlink"></category>
    <category term="networking"></category>
    <category term="self-hosting"></category>
    <category term="vpn"></category>
  </entry>
  <entry>
    <title>Ed25519 vs ECDSA: How Deterministic Nonces Ended a Recurring Bug</title>
    <link href="https://dixon.cx/blog/ed25519-vs-ecdsa-deterministic-nonces.html" rel="alternate" type="text/html"></link>
    <id>https://dixon.cx/blog/ed25519-vs-ecdsa-deterministic-nonces.html</id>
    <published>2026-09-11T19:01:36Z</published>
    <updated>2026-09-11T19:01:36Z</updated>
    <summary>How a reused ECDSA nonce leaks a private key, why Sony and Android wallets fell to it, and how Ed25519 designs the whole bug class out.</summary>
    <category term="Cryptography"></category>
    <category term="cryptography"></category>
    <category term="ed25519"></category>
    <category term="ecdsa"></category>
    <category term="go"></category>
    <category term="nonce-reuse"></category>
    <category term="digital-signatures"></category>
  </entry>
  <entry>
    <title>Flipper Blue++: Giving the Flipper Zero the Bluetooth Stack It Was Built For</title>
    <link href="https://dixon.cx/blog/flipper-bluepp-full-bluetooth-stack.html" rel="alternate" type="text/html"></link>
    <id>https://dixon.cx/blog/flipper-bluepp-full-bluetooth-stack.html</id>
    <published>2026-09-11T16:29:13Z</published>
    <updated>2026-09-11T16:29:13Z</updated>
    <summary>Why stock Flipper Zero firmware cannot scan or connect over BLE, the three patches that unlock the full stack, and how to drive it from your own app.</summary>
    <category term="Embedded"></category>
    <category term="flipper-zero"></category>
    <category term="bluetooth"></category>
    <category term="ble"></category>
    <category term="firmware"></category>
    <category term="stm32wb55"></category>
    <category term="embedded"></category>
  </entry>
  <entry>
    <title>Go HTTP Response Bodies: Why Close Alone Loses Connections</title>
    <link href="https://dixon.cx/blog/go-http-response-bodies-close-connection-reuse.html" rel="alternate" type="text/html"></link>
    <id>https://dixon.cx/blog/go-http-response-bodies-close-connection-reuse.html</id>
    <published>2026-09-11T03:35:40Z</published>
    <updated>2026-09-11T03:35:40Z</updated>
    <summary>Closing a Go HTTP response body prevents leaks, but HTTP/1 connection reuse depends on reaching EOF. Learn when to drain, cap or abandon a body.</summary>
    <category term="Go"></category>
    <category term="go"></category>
    <category term="net-http"></category>
    <category term="http"></category>
    <category term="connection-pooling"></category>
    <category term="networking"></category>
    <category term="performance"></category>
  </entry>
</feed>
