<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Posts on Tech Notes - A Developer's Journal</title><link>https://oypron.com/posts/</link><description>Recent content in Posts on Tech Notes - A Developer's Journal</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Sun, 08 Mar 2026 11:45:00 +0000</lastBuildDate><atom:link href="https://oypron.com/posts/index.xml" rel="self" type="application/rss+xml"/><item><title>Observability with OpenTelemetry: What's Worth It and What Isn't</title><link>https://oypron.com/posts/observability-with-opentelemetry/</link><pubDate>Sun, 08 Mar 2026 11:45:00 +0000</pubDate><guid>https://oypron.com/posts/observability-with-opentelemetry/</guid><description>&lt;p&gt;I&amp;rsquo;ve adopted OpenTelemetry on three different services over the last two years, with varying success. This post is the honest version of what I&amp;rsquo;ve learned: where it pays off, where the friction lives, and what I would do differently next time.&lt;/p&gt;
&lt;h2 id="the-three-signals-ranked-by-effort-vs-payoff"&gt;The three signals, ranked by effort vs payoff&lt;/h2&gt;
&lt;p&gt;OTel covers traces, metrics, and logs. They are not equally easy to adopt and they don&amp;rsquo;t deliver equal value.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Traces — high payoff, moderate effort.&lt;/strong&gt; The first time you see a flame graph showing exactly where a slow request spent its 800ms, all the instrumentation work feels worth it. Auto-instrumentation libraries cover most of what you need (HTTP, database, Redis, gRPC) so the upfront cost is mostly: install SDK, configure exporter, deploy. Worth doing first.&lt;/p&gt;</description></item><item><title>Postgres Performance Tuning: The First Five Things I Check</title><link>https://oypron.com/posts/postgres-performance-tuning/</link><pubDate>Mon, 12 Jan 2026 16:30:00 +0000</pubDate><guid>https://oypron.com/posts/postgres-performance-tuning/</guid><description>&lt;p&gt;When somebody hands me a Postgres database and says &amp;ldquo;it&amp;rsquo;s slow,&amp;rdquo; I work through the same checklist almost every time. None of these are exotic. They&amp;rsquo;re the boring, high-leverage things that solve maybe 80 percent of the cases I see before anyone has to think hard.&lt;/p&gt;
&lt;h2 id="1-explain-analyze-buffers-before-anything-else"&gt;1. EXPLAIN (ANALYZE, BUFFERS) before anything else&lt;/h2&gt;
&lt;p&gt;Theories about why a query is slow are mostly worthless. Run the query with &lt;code&gt;EXPLAIN (ANALYZE, BUFFERS)&lt;/code&gt; and read the output.&lt;/p&gt;</description></item><item><title>Kubernetes NetworkPolicy: A Practical Guide to Default-Deny</title><link>https://oypron.com/posts/kubernetes-network-policies/</link><pubDate>Wed, 05 Nov 2025 09:00:00 +0000</pubDate><guid>https://oypron.com/posts/kubernetes-network-policies/</guid><description>&lt;p&gt;The first time I tried to enforce NetworkPolicy in a real cluster, I broke DNS for an entire namespace and spent the next forty minutes wondering why every pod was returning &lt;code&gt;i/o timeout&lt;/code&gt;. This post is the guide I wish I had read first.&lt;/p&gt;
&lt;h2 id="the-mental-model"&gt;The mental model&lt;/h2&gt;
&lt;p&gt;A NetworkPolicy is a label-selector-driven firewall rule. It only does two things:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Selects pods&lt;/strong&gt; by label (in a single namespace).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Specifies allowed ingress, egress, or both&lt;/strong&gt; for those pods.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Three rules that took me too long to internalize:&lt;/p&gt;</description></item><item><title>A Worker Pool That Actually Shuts Down: Go Concurrency Patterns Revisited</title><link>https://oypron.com/posts/golang-concurrency-patterns/</link><pubDate>Mon, 22 Sep 2025 14:15:00 +0000</pubDate><guid>https://oypron.com/posts/golang-concurrency-patterns/</guid><description>&lt;p&gt;Worker pools are one of those patterns that looks trivial in a blog post and becomes surprisingly difficult in production. The version I keep coming back to is built around three rules: a single owner, explicit cancellation, and a bounded queue. This post walks through the version I actually paste into projects.&lt;/p&gt;
&lt;h2 id="the-naive-version"&gt;The naive version&lt;/h2&gt;
&lt;p&gt;Most worker pool examples on the internet look like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;jobs&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; make(&lt;span style="color:#66d9ef"&gt;chan&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Job&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt; &amp;lt; &lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;&lt;span style="color:#f92672"&gt;++&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;go&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;j&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;range&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;jobs&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;process&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;j&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This works for the happy path and falls apart everywhere else. There&amp;rsquo;s no way to wait for the workers to finish, no way to stop them early, and no way to know if &lt;code&gt;process&lt;/code&gt; panicked. If the producer crashes, the workers stay alive forever.&lt;/p&gt;</description></item><item><title>Hello World — Why I'm Starting This Blog</title><link>https://oypron.com/posts/hello-world/</link><pubDate>Fri, 15 Aug 2025 10:30:00 +0000</pubDate><guid>https://oypron.com/posts/hello-world/</guid><description>&lt;p&gt;After almost a decade of writing code professionally, I have built up a fairly large pile of half-finished notes, throwaway gists, and Slack messages to my future self. Most of them never see daylight again. This blog is an attempt to fix that.&lt;/p&gt;
&lt;h2 id="why-now"&gt;Why now&lt;/h2&gt;
&lt;p&gt;Earlier this year I rebuilt a service that had been quietly accumulating tech debt for three years. By the time I was done I had read through thousands of lines of code I had written years ago and barely recognized any of it. There were comments like &lt;code&gt;// TODO: figure this out later&lt;/code&gt; next to a perfectly reasonable explanation that I clearly knew at the time but no longer remembered. I wished, more than once, that I had written things down somewhere I would actually be able to find them.&lt;/p&gt;</description></item></channel></rss>