<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Posts on Jack's home on the web</title><link>https://cep.dev/posts/</link><description>Recent content in Posts on Jack's home on the web</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Mon, 06 Oct 2025 00:00:00 +0000</lastBuildDate><atom:link href="https://cep.dev/posts/index.xml" rel="self" type="application/rss+xml"/><item><title>Tracing large job failures to serial console bottlenecks from OOM events</title><link>https://cep.dev/posts/oom-killer-network-outage-serial-console/</link><pubDate>Mon, 06 Oct 2025 00:00:00 +0000</pubDate><guid>https://cep.dev/posts/oom-killer-network-outage-serial-console/</guid><description>&lt;figure&gt;&lt;img src="https://cep.dev/posts/oom-killer-network-outage-serial-console/images/hero-detective-timeline.svg"
 alt="Detective timeline: DNS timeouts (false lead), ENA logs, CPU 19, 20k processes, serial console bottleneck. Cork board with SOLVED stamp."&gt;&lt;figcaption&gt;
 &lt;p&gt;The investigation timeline: From false DNS timeout leads to discovering the real culprit—a serial console bottleneck causing 3+ minute network outages.&lt;/p&gt;
 &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h1 id="abstract"&gt;
 Abstract
 &lt;a class="heading-link" href="#abstract"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;Link to heading&lt;/span&gt;
 &lt;/a&gt;
&lt;/h1&gt;
&lt;p&gt;Often for machine learning workloads, a single node of a large job crashing can stall the entire job. &lt;a href="https://www.anthropic.com/" class="external-link" target="_blank" rel="noopener"&gt;We&lt;/a&gt;
run a &lt;a href="https://aws.amazon.com/blogs/containers/amazon-eks-enables-ultra-scale-ai-ml-workloads-with-support-for-100k-nodes-per-cluster/" class="external-link" target="_blank" rel="noopener"&gt;very large AWS EKS cluster&lt;/a&gt;
with large distributed workloads. This post is about investigating one issue where nodes would seemingly
go NotReady for several minutes without a clear cause, causing job failures.&lt;/p&gt;</description></item><item><title>My process to debug DNS timeouts in a large EKS cluster</title><link>https://cep.dev/posts/eks-dns-timeouts-sudo-hostname-lookups/</link><pubDate>Fri, 01 Aug 2025 17:01:02 +0000</pubDate><guid>https://cep.dev/posts/eks-dns-timeouts-sudo-hostname-lookups/</guid><description>&lt;h1 id="abstract"&gt;
 Abstract
 &lt;a class="heading-link" href="#abstract"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;Link to heading&lt;/span&gt;
 &lt;/a&gt;
&lt;/h1&gt;
&lt;p&gt;We run a &lt;a href="https://aws.amazon.com/blogs/containers/amazon-eks-enables-ultra-scale-ai-ml-workloads-with-support-for-100k-nodes-per-cluster/" class="external-link" target="_blank" rel="noopener"&gt;very large AWS EKS cluster&lt;/a&gt; with lots of interesting challenges. This post is about
a recent investigation into DNS resolution failures that we were able to root cause to an
Elastic Network Interface (ENI) packets per second (PPS) limit and a further root cause of
the combination of sudo defaults and ndots in our cluster DNS.&lt;/p&gt;
&lt;p&gt;This post talks about the investigation process and the resolution.&lt;/p&gt;</description></item><item><title>Permanent infrastructure as code state drift from gzip cloud-init</title><link>https://cep.dev/posts/gzip-userdata-persistent-state-drift/</link><pubDate>Sun, 15 Sep 2024 13:59:23 -0800</pubDate><guid>https://cep.dev/posts/gzip-userdata-persistent-state-drift/</guid><description>&lt;h2 id="setup"&gt;
 Setup
 &lt;a class="heading-link" href="#setup"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;Link to heading&lt;/span&gt;
 &lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Most cloud providers allow you to set commands to run when a host comes online. The general format for this is
called &lt;code&gt;cloud-init&lt;/code&gt; or &lt;code&gt;user-data&lt;/code&gt;. There&amp;rsquo;s full documentation for cloud-init &lt;a href="https://cloudinit.readthedocs.io/en/latest/" class="external-link" target="_blank" rel="noopener"&gt;here&lt;/a&gt;.
In my particular case, I had extra files I wanted to write to the host using &lt;a href="https://www.pulumi.com/" class="external-link" target="_blank" rel="noopener"&gt;pulumi&lt;/a&gt;.
To make it all fit, I was gzip compressing the files then &lt;a href="https://en.wikipedia.org/wiki/Base64" class="external-link" target="_blank" rel="noopener"&gt;base64&lt;/a&gt; encoding
the result.&lt;/p&gt;</description></item><item><title>I advise against changing the kubelet root directory</title><link>https://cep.dev/posts/adventure-trying-change-kubelet-rootdir/</link><pubDate>Sun, 21 Jul 2024 13:59:23 -0800</pubDate><guid>https://cep.dev/posts/adventure-trying-change-kubelet-rootdir/</guid><description>&lt;figure&gt;&lt;img src="https://cep.dev/posts/adventure-trying-change-kubelet-rootdir/images/cover.webp"
 alt="Robots and hard drives"&gt;&lt;figcaption&gt;
 &lt;p&gt;Fighting with hard drives&lt;/p&gt;
 &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h2 id="tldr"&gt;
 TL;DR
 &lt;a class="heading-link" href="#tldr"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;Link to heading&lt;/span&gt;
 &lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Changing kubelet&amp;rsquo;s root directory can break CSI drivers and other components. You can work around this, but the
effort isn&amp;rsquo;t worth it: stick with the default /var/lib/kubelet.&lt;/p&gt;
&lt;h2 id="motivation"&gt;
 Motivation
 &lt;a class="heading-link" href="#motivation"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;Link to heading&lt;/span&gt;
 &lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;I was setting up Kubernetes &lt;a href="https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/" class="external-link" target="_blank" rel="noopener"&gt;kubelet&lt;/a&gt;
on a host with numerous &lt;a href="https://en.wikipedia.org/wiki/NVM_Express" class="external-link" target="_blank" rel="noopener"&gt;NVMe&lt;/a&gt; drives .
I thought &amp;ldquo;Let&amp;rsquo;s use this for
&lt;a href="https://kubernetes.io/docs/concepts/storage/ephemeral-volumes/" class="external-link" target="_blank" rel="noopener"&gt;ephemeral-storage&lt;/a&gt; in Kubernetes&amp;rdquo;. The host had
no need for all these drives and Kubernetes could allow pods to claim them for ephemeral storage.&lt;/p&gt;</description></item><item><title>Debugging a kubernetes node</title><link>https://cep.dev/posts/debugging-kubernetes-node/</link><pubDate>Thu, 25 Apr 2024 13:59:23 -0800</pubDate><guid>https://cep.dev/posts/debugging-kubernetes-node/</guid><description>&lt;p&gt;Do you ever need to debug a node on kubernetes? Maybe the networking is broken, or you need to check
something else out? The &lt;a href="https://github.com/nicolaka/netshoot" class="external-link" target="_blank" rel="noopener"&gt;netshoot&lt;/a&gt; docker container contains a large number of
helpful network tools like tcpdump, iperf, and more. Use a script
&lt;a href="https://github.com/cep21/jackbash/blob/master/bin/kc-netshoot.sh" class="external-link" target="_blank" rel="noopener"&gt;like this&lt;/a&gt; to kubectl directly to a node with escalated
privileges. Once in, try &lt;code&gt;tcpdump -i any&lt;/code&gt; to see all network traffic on the node.&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;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#!/bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;&lt;/span&gt;set -exuo pipefail
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#f92672"&gt;[[&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;1-&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;]]&lt;/span&gt;; &lt;span style="color:#66d9ef"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; kubectl run &lt;span style="color:#e6db74"&gt;&amp;#34;netshoot-&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;$(&lt;/span&gt;whoami&lt;span style="color:#66d9ef"&gt;)&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; --rm -i --tty --image nicolaka/netshoot -- /bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; kubectl run &lt;span style="color:#e6db74"&gt;&amp;#34;netshoot-&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;$(&lt;/span&gt;whoami&lt;span style="color:#66d9ef"&gt;)&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; --rm -i --tty --image nicolaka/netshoot &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;&lt;/span&gt; --overrides&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;{ 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;spec&amp;#34;: {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;hostNetwork&amp;#34;: true,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;tolerations&amp;#34;: [{
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;key&amp;#34;: &amp;#34;&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;operator&amp;#34;: &amp;#34;Exists&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; }],
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;nodeSelector&amp;#34;: {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;kubernetes.io/hostname&amp;#34;: &amp;#34;&amp;#39;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;1&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;containers&amp;#34;: [{
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;name&amp;#34;: &amp;#34;netshoot&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;image&amp;#34;: &amp;#34;nicolaka/netshoot&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;securityContext&amp;#34;: {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;privileged&amp;#34;: true
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;command&amp;#34;: [&amp;#34;/bin/bash&amp;#34;],
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;stdin&amp;#34;: true,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;tty&amp;#34;: true
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; }]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; }&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For example, I can run this to get a shell on a node:&lt;/p&gt;</description></item><item><title>How I do sprint planning meetings for a software team</title><link>https://cep.dev/posts/sprint-planning-script/</link><pubDate>Tue, 27 Feb 2024 07:00:08 -0800</pubDate><guid>https://cep.dev/posts/sprint-planning-script/</guid><description>&lt;figure&gt;&lt;img src="https://cep.dev/posts/sprint-planning-script/images/team-planning.jpg"
 alt="Picture of people looking at a monitor"&gt;&lt;figcaption&gt;
 &lt;p&gt;Image from &lt;a href="https://unsplash.com/photos/five-person-by-table-watching-turned-on-white-imac-vbxyFxlgpjM" class="external-link" target="_blank" rel="noopener"&gt;UnSplash&lt;/a&gt;&lt;/p&gt;
 &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h2 id="preface"&gt;
 Preface
 &lt;a class="heading-link" href="#preface"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;Link to heading&lt;/span&gt;
 &lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;This post describes how I&amp;rsquo;ve been conducting sprint planning on my current team.
It deviates from standard agile in a few ways. I document how and why towards the bottom.
I&amp;rsquo;ve found this format works well for us, but there is no process that works for everyone.
I script out the sprint planning process to keep it focused and make sure we don&amp;rsquo;t forget
to cover anything important.&lt;/p&gt;</description></item><item><title>(Almost) Every infrastructure decision I endorse or regret after 4 years running infrastructure at a startup</title><link>https://cep.dev/posts/every-infrastructure-decision-i-endorse-or-regret-after-4-years-running-infrastructure-at-a-startup/</link><pubDate>Thu, 01 Feb 2024 13:59:47 -0800</pubDate><guid>https://cep.dev/posts/every-infrastructure-decision-i-endorse-or-regret-after-4-years-running-infrastructure-at-a-startup/</guid><description>&lt;figure&gt;&lt;img src="https://cep.dev/posts/every-infrastructure-decision-i-endorse-or-regret-after-4-years-running-infrastructure-at-a-startup/images/network-image.jpg"
 alt="Picture of networking"&gt;&lt;figcaption&gt;
 &lt;p&gt;Image from UnSplash&lt;/p&gt;
 &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;I&amp;rsquo;ve led infrastructure at a &lt;a href="https://cresta.com/careers/" class="external-link" target="_blank" rel="noopener"&gt;startup&lt;/a&gt; for the past 4 years that has had
to scale quickly. From the beginning I made some core decisions that the
company has had to stick to, for better or worse, these past four years. This post
will list some of the major decisions made and if I endorse them for your
startup, or if I regret them and advise you to pick something else.&lt;/p&gt;</description></item><item><title>Using Docker and Terraform for hermetic AWS Lambda CI/CD</title><link>https://cep.dev/posts/using-docker-and-terraform-for-hermetic-aws-lambda-cicd/</link><pubDate>Thu, 30 Apr 2020 17:01:00 +0000</pubDate><guid>https://cep.dev/posts/using-docker-and-terraform-for-hermetic-aws-lambda-cicd/</guid><description>&lt;h2 id="context"&gt;
 Context
 &lt;a class="heading-link" href="#context"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;Link to heading&lt;/span&gt;
 &lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;We are using AWS Auora to manager our databases and I want to setup automatic rotation of database passwords. I
start by storing them in &lt;a href="https://aws.amazon.com/secrets-manager/" class="external-link" target="_blank" rel="noopener"&gt;AWS Secrets Manager&lt;/a&gt;. AWS actually releases
&lt;a href="https://github.com/aws-samples/aws-secrets-manager-rotation-lambdas/blob/master/SecretsManagerRDSPostgreSQLRotationMultiUser/lambda_function.py" class="external-link" target="_blank" rel="noopener"&gt;publicly usable rotations for PostgreSQL&lt;/a&gt;,
but I want to add the extra fields &lt;code&gt;connstring&lt;/code&gt; and &lt;code&gt;host_ro&lt;/code&gt; so clients can directly pull both the read only Auora DNS
and a full PostgreSQL connection string.&lt;/p&gt;</description></item><item><title>After using both, I regretted switching from Terraform to CloudFormation</title><link>https://cep.dev/posts/after-using-both-i-regretted-switching-from-terraform-to-cloudformation/</link><pubDate>Thu, 10 Oct 2019 17:01:01 +0000</pubDate><guid>https://cep.dev/posts/after-using-both-i-regretted-switching-from-terraform-to-cloudformation/</guid><description>&lt;p&gt;An unambiguous best practice for systems is to codify your infrastructure in a repeatable text format, rather than
clicks in a UI.
The common name for this is &lt;a href="https://en.wikipedia.org/wiki/Infrastructure_as_code" class="external-link" target="_blank" rel="noopener"&gt;Infrastructure as Code&lt;/a&gt;. By far, the two most popular ways to do this, especially in
AWS, are &lt;a href="https://www.terraform.io/" class="external-link" target="_blank" rel="noopener"&gt;Terraform&lt;/a&gt; and &lt;a href="https://aws.amazon.com/cloudformation/" class="external-link" target="_blank" rel="noopener"&gt;CloudFormation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I used Terraform for about 3 years &lt;a href="https://www.signalfx.com/" class="external-link" target="_blank" rel="noopener"&gt;at a startup&lt;/a&gt; before working for
&lt;a href="https://www.twitch.tv" class="external-link" target="_blank" rel="noopener"&gt;Twitch&lt;/a&gt;(AKA &lt;a href="https://www.businessinsider.com/amazon-buys-twitch-2014-8" class="external-link" target="_blank" rel="noopener"&gt;Amazon Jr&lt;/a&gt;) where I used Terraform very heavily before the company pushed
hard to switch to all things Amazon, including CloudFormation. I tried very hard to develop best practices around both
and used each for very complicated operational setups that spanned organizations. After thinking hard about the switch
from Terraform to CloudFormation, I feel strongly that Terraform is probably the right choice for your company.&lt;/p&gt;</description></item><item><title>Closure driven tests: an alternative style to table driven tests in go</title><link>https://cep.dev/posts/closure-driven-tests-an-alternative-style-to-table-driven-tests-in-go/</link><pubDate>Tue, 17 Sep 2019 17:01:03 +0000</pubDate><guid>https://cep.dev/posts/closure-driven-tests-an-alternative-style-to-table-driven-tests-in-go/</guid><description>&lt;p&gt;&lt;a href="https://github.com/golang/go/wiki/TableDrivenTests" class="external-link" target="_blank" rel="noopener"&gt;Table driven tests&lt;/a&gt; are a popular model for testing in Go and a clear improvement to traditional testing of
one function per case. However, there’s an alternative style that can often be clearer than table driven tests
that relies on &lt;a href="https://tour.golang.org/moretypes/25" class="external-link" target="_blank" rel="noopener"&gt;function closures&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I’ll reference the example code on Dave Cheney’s post &lt;a href="https://dave.cheney.net/2019/05/07/prefer-table-driven-tests" class="external-link" target="_blank" rel="noopener"&gt;Prefer table driven tests&lt;/a&gt; for my
examples.&lt;/p&gt;
&lt;h2 id="the-original-way"&gt;
 The original way
 &lt;a class="heading-link" href="#the-original-way"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;Link to heading&lt;/span&gt;
 &lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;The code we want to test is a function that splits strings.&lt;/p&gt;</description></item><item><title>Using Go 1.13’s new ReportMetric API to benchmark t-digest implementations</title><link>https://cep.dev/posts/using-go-1-13s-new-reportmetric-api-to-benchmark-tdigest-implementations/</link><pubDate>Wed, 11 Sep 2019 16:01:01 +0000</pubDate><guid>https://cep.dev/posts/using-go-1-13s-new-reportmetric-api-to-benchmark-tdigest-implementations/</guid><description>&lt;p&gt;Histograms are an important part of metrics and monitoring. Unfortunately, it is computationally expensive to
accurately calculate a histogram or quantile value. A workaround is to use an approximation and a great one to
use is &lt;a href="https://github.com/tdunning/t-digest" class="external-link" target="_blank" rel="noopener"&gt;t-digest&lt;/a&gt;. Unfortunately again, there’s no such thing as an accurate approximation. There are various
t-digest implementations in Go, but they do things slightly differently and there’s no way to track how accurate
their approximations are over time and no great way for consumers of quantile approximation libraries to benchmark
them against each other.&lt;/p&gt;</description></item><item><title>Interface Contracts Matter</title><link>https://cep.dev/posts/interface-contracts-matter/</link><pubDate>Wed, 07 Aug 2019 16:31:02 +0000</pubDate><guid>https://cep.dev/posts/interface-contracts-matter/</guid><description>&lt;p&gt;A recent &lt;a href="https://github.com/go-redis/redis/issues/1113" class="external-link" target="_blank" rel="noopener"&gt;vulnerability&lt;/a&gt; in the &lt;a href="https://github.com/go-redis/redis" class="external-link" target="_blank" rel="noopener"&gt;go-redis&lt;/a&gt;
library allowed correctly configured clients to return the results of other redis commands in the event of redis
failures. While all code is subject to bugs, this one could have been prevented if proper care was taken when
creating and using interfaces.&lt;/p&gt;
&lt;h1 id="bug-behavior"&gt;
 Bug behavior
 &lt;a class="heading-link" href="#bug-behavior"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;Link to heading&lt;/span&gt;
 &lt;/a&gt;
&lt;/h1&gt;
&lt;p&gt;Most clients reuse TCP connections between RPC calls to eliminate the delay of TCP connection overhead. TCP connections
have both an input and output stream. &lt;a href="https://redis.io/" class="external-link" target="_blank" rel="noopener"&gt;Redis&lt;/a&gt; operates on a request/response pattern where commands
are shared on the same socket by sending multiple requests and expecting multiple responses. Most of the time responses
are read after the request is sent. For example, there could be two requests to get the key “money:*” for two different
users with jack having $200 and john having $100.&lt;/p&gt;</description></item><item><title>Go’s wrapped return pattern to clean up objects with background goroutines</title><link>https://cep.dev/posts/gos-wrapped-return-pattern-to-clean-up-objects-with-background-goroutines/</link><pubDate>Tue, 02 Jul 2019 17:01:01 +0000</pubDate><guid>https://cep.dev/posts/gos-wrapped-return-pattern-to-clean-up-objects-with-background-goroutines/</guid><description>&lt;h1 id="problem"&gt;
 Problem
 &lt;a class="heading-link" href="#problem"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;Link to heading&lt;/span&gt;
 &lt;/a&gt;
&lt;/h1&gt;
&lt;p&gt;You have a constructor function that creates an object with a background goroutine. You want the object to garbage
collect itself even if people don’t explicitly close it. This isn’t possible since since the background goroutine
is always running and pointing to your created object.&lt;/p&gt;
&lt;h1 id="solution"&gt;
 Solution
 &lt;a class="heading-link" href="#solution"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;Link to heading&lt;/span&gt;
 &lt;/a&gt;
&lt;/h1&gt;
&lt;p&gt;Wrap the returned object and use a finalizer on the returned object to shut down the background goroutine.&lt;/p&gt;</description></item><item><title>Design better software abstractions using bipartite composition</title><link>https://cep.dev/posts/design-better-software-abstractions-using-bipartite-composition/</link><pubDate>Wed, 29 May 2019 17:04:00 +0000</pubDate><guid>https://cep.dev/posts/design-better-software-abstractions-using-bipartite-composition/</guid><description>&lt;h1 id="problem"&gt;
 Problem
 &lt;a class="heading-link" href="#problem"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;Link to heading&lt;/span&gt;
 &lt;/a&gt;
&lt;/h1&gt;
&lt;p&gt;You’ve written an object or class. It’s somewhat complex and you want to iterate ways to better abstract your
code but are unsure how to start. There exists &lt;a href="https://en.wikipedia.org/wiki/SOLID" class="external-link" target="_blank" rel="noopener"&gt;documentation&lt;/a&gt; about what a
good abstraction looks like, but no concrete iterative steps.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Being deep inside your own code can make you blind to obvious alternatives.&lt;/p&gt;&lt;/blockquote&gt;
&lt;h1 id="solution"&gt;
 Solution
 &lt;a class="heading-link" href="#solution"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;Link to heading&lt;/span&gt;
 &lt;/a&gt;
&lt;/h1&gt;
&lt;p&gt;Create a &lt;a href="https://en.wikipedia.org/wiki/Bipartite_graph" class="external-link" target="_blank" rel="noopener"&gt;bipartite graph&lt;/a&gt; of instance methods and
&lt;a href="https://en.wikipedia.org/wiki/Member_variable" class="external-link" target="_blank" rel="noopener"&gt;member variables&lt;/a&gt;. Draw edges between methods and the variables they
use. Then move &lt;a href="https://en.wikipedia.org/wiki/Connectivity_%28graph_theory%29" class="external-link" target="_blank" rel="noopener"&gt;isolated&lt;/a&gt;
&lt;a href="https://en.wikipedia.org/wiki/Component_%28graph_theory%29" class="external-link" target="_blank" rel="noopener"&gt;components&lt;/a&gt; into separate classes.&lt;/p&gt;</description></item><item><title>Go’s append is not always thread safe</title><link>https://cep.dev/posts/gos-append-is-not-always-thread-safe/</link><pubDate>Tue, 12 Jun 2018 16:01:01 +0000</pubDate><guid>https://cep.dev/posts/gos-append-is-not-always-thread-safe/</guid><description>&lt;h1 id="problem-example"&gt;
 Problem Example
 &lt;a class="heading-link" href="#problem-example"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;Link to heading&lt;/span&gt;
 &lt;/a&gt;
&lt;/h1&gt;
&lt;p&gt;I commonly see bugs appending to slices in Go in a way that is not thread safe. A simple example is the unit
tests below. This test has two goroutines &lt;a href="https://golang.org/pkg/builtin/#append" class="external-link" target="_blank" rel="noopener"&gt;append&lt;/a&gt; to the same slice.
If you run this test with the &lt;a href="https://golang.org/doc/articles/race_detector.html" class="external-link" target="_blank" rel="noopener"&gt;-race&lt;/a&gt; flag, it works just fine.&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;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;package&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&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 style="color:#f92672"&gt;import&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;sync&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;testing&amp;#34;&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 style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;TestAppend&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;t&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;testing&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;T&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;x&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; []&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;{&lt;span style="color:#e6db74"&gt;&amp;#34;start&amp;#34;&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 style="color:#a6e22e"&gt;wg&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;sync&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;WaitGroup&lt;/span&gt;{}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;wg&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Add&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;2&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;defer&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;wg&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Done&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;y&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; append(&lt;span style="color:#a6e22e"&gt;x&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;hello&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;world&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;t&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Log&lt;/span&gt;(cap(&lt;span style="color:#a6e22e"&gt;y&lt;/span&gt;), len(&lt;span style="color:#a6e22e"&gt;y&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 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;defer&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;wg&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Done&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;z&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; append(&lt;span style="color:#a6e22e"&gt;x&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;goodbye&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;bob&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;t&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Log&lt;/span&gt;(cap(&lt;span style="color:#a6e22e"&gt;z&lt;/span&gt;), len(&lt;span style="color:#a6e22e"&gt;z&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 style="color:#a6e22e"&gt;wg&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Wait&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;Now, let’s change the code just slightly to create the &lt;code&gt;x&lt;/code&gt; slice with more spare capacity. The only thing that
changed was line 9.&lt;/p&gt;</description></item><item><title>Using Go 1.10 new trace features to debug an integration test</title><link>https://cep.dev/posts/using-go-1-10-new-trace-features-to-debug-an-integration-test/</link><pubDate>Fri, 26 Jan 2018 20:08:28 +0000</pubDate><guid>https://cep.dev/posts/using-go-1-10-new-trace-features-to-debug-an-integration-test/</guid><description>&lt;p&gt;I had an integration test that was very complex (most are, sadly) and took too long to start. I was able to diagnose
why using new features of Go’s 1.10 trace tool. This post describes my workflow and what led me there.&lt;/p&gt;
&lt;p&gt;The example code I’m using for this post is at &lt;a href="https://github.com/cep21/trace-110" class="external-link" target="_blank" rel="noopener"&gt;https://github.com/cep21/trace-110&lt;/a&gt;.
My integration test was a bit more complex, but generally had startup that was slow due to a single goroutine out of many
that did lots of different things. In this example, &lt;strong&gt;takeIO&lt;/strong&gt; is similar to the “startup” part of my integration test.&lt;/p&gt;</description></item><item><title>Aspects of a good Go library</title><link>https://cep.dev/posts/aspects-of-a-good-go-library/</link><pubDate>Mon, 18 Dec 2017 19:32:56 +0000</pubDate><guid>https://cep.dev/posts/aspects-of-a-good-go-library/</guid><description>&lt;p&gt;A short checklist of what I wish for in a good Go library, in no particular order. This is a companion to the
&lt;a href="https://golang.org/doc/effective_go.html" class="external-link" target="_blank" rel="noopener"&gt;effective go&lt;/a&gt; list, &lt;a href="https://github.com/golang/go/wiki/CodeReviewComments" class="external-link" target="_blank" rel="noopener"&gt;Go code review comments&lt;/a&gt; list, and &lt;a href="https://go-proverbs.github.io/" class="external-link" target="_blank" rel="noopener"&gt;Go proverbs&lt;/a&gt; list.&lt;/p&gt;
&lt;p&gt;In general, when given two reasonable ways to do something, defer to the option that does not violate these rules.
Bend these rules only with a strong explanation why.&lt;/p&gt;
&lt;h2 id="dependencies"&gt;
 Dependencies
 &lt;a class="heading-link" href="#dependencies"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;Link to heading&lt;/span&gt;
 &lt;/a&gt;
&lt;/h2&gt;
&lt;h3 id="tagged-library-versions"&gt;
 Tagged library versions
 &lt;a class="heading-link" href="#tagged-library-versions"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;Link to heading&lt;/span&gt;
 &lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Use git tags to version your library. Semantic versioning is a reasonable system. If you
&lt;a href="https://news.ycombinator.com/item?id=13378637" class="external-link" target="_blank" rel="noopener"&gt;care enough to disagree&lt;/a&gt; with semantic versioning, then you’re not the target here. :)&lt;/p&gt;</description></item><item><title>Go Experience report: Go’s type system</title><link>https://cep.dev/posts/go-experience-report-gos-type-system/</link><pubDate>Thu, 07 Sep 2017 16:01:03 +0000</pubDate><guid>https://cep.dev/posts/go-experience-report-gos-type-system/</guid><description>&lt;h1 id="what-i-wanted-to-do"&gt;
 What I wanted to do
 &lt;a class="heading-link" href="#what-i-wanted-to-do"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;Link to heading&lt;/span&gt;
 &lt;/a&gt;
&lt;/h1&gt;
&lt;h2 id="todays-pkgerrors"&gt;
 Today’s pkg/errors
 &lt;a class="heading-link" href="#todays-pkgerrors"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;Link to heading&lt;/span&gt;
 &lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Package &lt;a href="https://github.com/pkg/errors" class="external-link" target="_blank" rel="noopener"&gt;errors&lt;/a&gt; is a popular go error wrapping package.
The &lt;a href="https://github.com/pkg/errors/blob/c605e284fe17294bda444b34710735b29d1a9d90/stack.go#L80" class="external-link" target="_blank" rel="noopener"&gt;StackTrace&lt;/a&gt; type
represents the stack trace with an []Frame. Errors wrapped by package errors implicitly implement the stackTracer
interface, which allows users to extract stack information.&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;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;StackTrace&lt;/span&gt; []&lt;span style="color:#a6e22e"&gt;Frame&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Frame&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;uintptr&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 style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;stackTracer&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;interface&lt;/span&gt; { 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;StackTrace&lt;/span&gt;() &lt;span style="color:#a6e22e"&gt;errors&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;StackTrace&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;Simultaneously to this, there exist libraries that would like to extract stack frame information from errors, if
it’s present. One example is the &lt;a href="https://rollbar.com/" class="external-link" target="_blank" rel="noopener"&gt;rollbar&lt;/a&gt; logging library, which allows logging errors with
the stack trace that created them. The only way for a rollbar logging library to support pkg/errors is to import
the library directly and type assert for a StackTrace function.&lt;/p&gt;</description></item><item><title>Interface wrapping method erasure</title><link>https://cep.dev/posts/interface-wrapping-method-erasure/</link><pubDate>Wed, 26 Jul 2017 14:02:39 +0000</pubDate><guid>https://cep.dev/posts/interface-wrapping-method-erasure/</guid><description>&lt;h1 id="problem"&gt;
 Problem
 &lt;a class="heading-link" href="#problem"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;Link to heading&lt;/span&gt;
 &lt;/a&gt;
&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;The go language spec has no way to simultaneously add or augment behavior to an interface while maintaining commonly
accepted best programming practices around minimal interface design&lt;/strong&gt;. While not unique to Go itself, a combination
of Go’s feature set and evolved best practices have caused Go library authors to suffer disproportionately to other
language developers.&lt;/p&gt;
&lt;h1 id="abstract-example"&gt;
 Abstract example
 &lt;a class="heading-link" href="#abstract-example"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;Link to heading&lt;/span&gt;
 &lt;/a&gt;
&lt;/h1&gt;
&lt;p&gt;Given an interface I of a concrete type S, there is no way to add behavior to I while returning a type of I that also
implements the functions of S, without knowing S’s functions a priori. Specifically the below example will panic.&lt;/p&gt;</description></item><item><title>DynamoDB trivia: reads throttled but under capacity</title><link>https://cep.dev/posts/dynamodb-trivia-reads-throttled-but-under-capacity/</link><pubDate>Mon, 23 Jan 2017 21:02:13 +0000</pubDate><guid>https://cep.dev/posts/dynamodb-trivia-reads-throttled-but-under-capacity/</guid><description>&lt;p&gt;I get woken up to an alert about read capacity on one of my DynamoDB tables. Here is the error being logged.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;ProvisionedThroughputExceededException: The level of configured provisioned throughput for the table was exceeded.
Consider increasing your provisioning level with the UpdateTable API.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;When I load my CloudWatch graphs, and it appears I’m well below capacity.&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cep.dev/posts/dynamodb-trivia-reads-throttled-but-under-capacity/images/dynamo-throttle-graph.png"
 alt="Two graphs: dynamodb read capacity and dynamodb throttled requests"&gt;&lt;figcaption&gt;
 &lt;p&gt;Cloudwatch graph of DynamoDB metrics.&lt;/p&gt;</description></item><item><title>Creating custom Go profiles with pprof</title><link>https://cep.dev/posts/creating-custom-go-profiles-with-pprof/</link><pubDate>Mon, 19 Dec 2016 18:01:02 +0000</pubDate><guid>https://cep.dev/posts/creating-custom-go-profiles-with-pprof/</guid><description>&lt;p&gt;Go’s pprof package is frequently used for heap and CPU profiles, but a little used feature of the package is
being able to create custom profiles. Custom profiles are useful for tracking down leaked resources and
troublesome stack traces that are abusing a library’s API.&lt;/p&gt;
&lt;h1 id="profile"&gt;
 Profile
 &lt;a class="heading-link" href="#profile"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;Link to heading&lt;/span&gt;
 &lt;/a&gt;
&lt;/h1&gt;
&lt;p&gt;From the &lt;a href="https://golang.org/pkg/runtime/pprof/#Profile" class="external-link" target="_blank" rel="noopener"&gt;godoc for pprof&lt;/a&gt; itself:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A Profile is a collection of stack traces showing the call sequences that led to instances of a particular event,
such as allocation. Packages can create and maintain their own profiles; the most common use is for tracking
resources that must be explicitly closed, such as files or network connections.&lt;/p&gt;</description></item><item><title>What “accept interfaces, return structs” means in Go</title><link>https://cep.dev/posts/what-accept-interfaces-return-structs-means-in-go/</link><pubDate>Mon, 05 Dec 2016 18:01:01 +0000</pubDate><guid>https://cep.dev/posts/what-accept-interfaces-return-structs-means-in-go/</guid><description>&lt;h4 id="not-lacking-nuance"&gt;
 Not lacking nuance
 &lt;a class="heading-link" href="#not-lacking-nuance"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;Link to heading&lt;/span&gt;
 &lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;I’ve mentioned a general guideline of &lt;em&gt;accept interfaces, return structs&lt;/em&gt; in a &lt;a href="https://cep.dev/posts/preemptive-interface-antipattern-in-go" &gt;previous post&lt;/a&gt; and multiple times
on code reviews to coworkers, but often get the question “Why”. Especially since this isn’t a hard rule. The crux of
the idea, and understanding when to bend it, is in the balance of avoiding preemptive abstractions while maintaining
flexibility.&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cep.dev/posts/what-accept-interfaces-return-structs-means-in-go/images/1.png"
 alt="A picture of a gopher with no outline"&gt;&lt;figcaption&gt;
 &lt;p&gt;The abstract gopher&lt;/p&gt;</description></item><item><title>Go race condition trivia</title><link>https://cep.dev/posts/go-race-condition-trivia/</link><pubDate>Tue, 15 Nov 2016 17:01:02 +0000</pubDate><guid>https://cep.dev/posts/go-race-condition-trivia/</guid><description>&lt;p&gt;I recently ran into a -race error message that stumped me for a while, so I’ll retell it here in phases to see if you can catch it.&lt;/p&gt;
&lt;h1 id="the-code"&gt;
 The code
 &lt;a class="heading-link" href="#the-code"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;Link to heading&lt;/span&gt;
 &lt;/a&gt;
&lt;/h1&gt;
&lt;p&gt;The intent of the &lt;a href="https://hackernoon.com/tagged/code" class="external-link" target="_blank" rel="noopener"&gt;code&lt;/a&gt; was a service abstraction that ran a goroutine in the background to send runtime stats to &lt;a href="https://github.com/etsy/statsd" class="external-link" target="_blank" rel="noopener"&gt;Stastd&lt;/a&gt;. A small example of the code follows:&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;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Stats&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;prev&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;runtime&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;MemStats&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 style="color:#66d9ef"&gt;func&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;p&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;Stats&lt;/span&gt;) &lt;span style="color:#a6e22e"&gt;stats&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;ms&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;runtime&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;MemStats&lt;/span&gt;{}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;runtime&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;ReadMemStats&lt;/span&gt;(&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;ms&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;mallocCount&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ms&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Mallocs&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;p&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;prev&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Mallocs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;malloc change is&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;mallocCount&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;p&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;prev&lt;/span&gt; = &lt;span style="color:#a6e22e"&gt;ms&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 style="color:#66d9ef"&gt;func&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;p&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;Stats&lt;/span&gt;) &lt;span style="color:#a6e22e"&gt;Loop&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;ctx&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;context&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Context&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;runtime&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;ReadMemStats&lt;/span&gt;(&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;p&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;prev&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&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;-&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;time&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;After&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;time&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Millisecond&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&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:#a6e22e"&gt;p&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;stats&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;-&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;ctx&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Done&lt;/span&gt;():
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&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;You can be 100% sure that I never run Loop() for the same Stats struct. And
you’re 100% sure I only make a single Stats{} struct in my program. Before reading forward, inspect the above code and see if you can find the &lt;a href="https://hackernoon.com/tagged/race" class="external-link" target="_blank" rel="noopener"&gt;race&lt;/a&gt; condition I hit while using Stats.&lt;/p&gt;</description></item><item><title>For Go builtins, nil and empty read the same</title><link>https://cep.dev/posts/for-go-builtins-nil-and-empty-read-the-same/</link><pubDate>Wed, 21 Sep 2016 16:44:29 +0000</pubDate><guid>https://cep.dev/posts/for-go-builtins-nil-and-empty-read-the-same/</guid><description>&lt;p&gt;An interesting property of Go’s built-in data structures is that read operations work even when they are nil!
Not only that, but read operations on nil built-in structures behave &lt;em&gt;just as if&lt;/em&gt; they are non-nil but empty.
This is different from other languages and allows some interesting properties of structures in Go. Here is a
full &lt;a href="https://play.golang.org/p/KZktHi9Ht7" class="external-link" target="_blank" rel="noopener"&gt;playground link&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id="why-nil-matters-for-built-in-structures"&gt;
 Why nil matters for built-in structures
 &lt;a class="heading-link" href="#why-nil-matters-for-built-in-structures"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;Link to heading&lt;/span&gt;
 &lt;/a&gt;
&lt;/h1&gt;
&lt;p&gt;Go does not have a way to force constructors for structs. The closest we can get is making the struct private and
documenting users to get an instance from a function named &lt;strong&gt;&lt;em&gt;New&lt;/em&gt;&lt;/strong&gt;. This means there’s no way to initialize a
member variable of a struct before people use it. Any maps, channels, or slices in your struct will start as nil.&lt;/p&gt;</description></item><item><title>Go 1.7 httptrace and context debug patterns</title><link>https://cep.dev/posts/go-17-httptrace-and-context-debug-patterns/</link><pubDate>Mon, 29 Aug 2016 17:01:02 +0000</pubDate><guid>https://cep.dev/posts/go-17-httptrace-and-context-debug-patterns/</guid><description>&lt;p&gt;Package &lt;a href="https://golang.org/pkg/net/http/httptrace/" class="external-link" target="_blank" rel="noopener"&gt;httptrace&lt;/a&gt; is a new addition in Go 1.7 that allows users to trace the steps of a HTTP request.
This package also models an interesting design pattern around adding optional debugging to a library. However,
it’s not the only way to accomplish this goal. I’ll briefly overview the package and provide alternative
implementations for httptrace.&lt;/p&gt;
&lt;h1 id="httptrace"&gt;
 httptrace
 &lt;a class="heading-link" href="#httptrace"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;Link to heading&lt;/span&gt;
 &lt;/a&gt;
&lt;/h1&gt;
&lt;p&gt;The basic idea of httptrace is that a laundry list of callbacks are optionally attached to a &lt;a href="https://golang.org/pkg/context/#Context" class="external-link" target="_blank" rel="noopener"&gt;Context&lt;/a&gt; object
that is added to a HTTP &lt;a href="https://golang.org/pkg/net/http/#Request.WithContext" class="external-link" target="_blank" rel="noopener"&gt;request&lt;/a&gt;. During the inner workings of the request, if
&lt;a href="https://github.com/golang/go/blob/release-branch.go1.7/src/net/http/transport.go#L309" class="external-link" target="_blank" rel="noopener"&gt;any of these callbacks are set&lt;/a&gt;, they are called during different stages of the request.&lt;/p&gt;</description></item><item><title>How to correctly use context.Context in Go 1.7</title><link>https://cep.dev/posts/how-to-correctly-use-context-context-in-go-17/</link><pubDate>Tue, 19 Jul 2016 15:56:02 +0000</pubDate><guid>https://cep.dev/posts/how-to-correctly-use-context-context-in-go-17/</guid><description>&lt;p&gt;This post will talk about a new library in Go 1.7, the context library, and when or how to correctly use it.
Required reading to start is &lt;a href="https://blog.golang.org/context" class="external-link" target="_blank" rel="noopener"&gt;the introductory post&lt;/a&gt; that talks a bit about the
library and generally how it is used. You can read &lt;a href="https://tip.golang.org/pkg/context/" class="external-link" target="_blank" rel="noopener"&gt;documentation for the context library on tip.golang.org&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id="how-to-integrate-context-into-your-api"&gt;
 How to integrate Context into your API
 &lt;a class="heading-link" href="#how-to-integrate-context-into-your-api"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;Link to heading&lt;/span&gt;
 &lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;The most important thing to remember when integrating Context into your API is that it is intended to be request
scoped. For example, it would make sense to exist along a single database query, but wouldn’t make sense to exist
along a database object.&lt;/p&gt;</description></item><item><title>Go client library best practices</title><link>https://cep.dev/posts/go-client-library-best-practices/</link><pubDate>Tue, 05 Jul 2016 17:52:53 +0000</pubDate><guid>https://cep.dev/posts/go-client-library-best-practices/</guid><description>&lt;p&gt;This post describes what I feel are best practices when creating a client library for a service. The
initial setup is that you’re writing a library with an API to talk to a RESTful service over HTTPS, and all
the library needs to do is return JSON unmarshalled objects. I’ll use some examples from
a &lt;a href="https://github.com/cep21/smitego" class="external-link" target="_blank" rel="noopener"&gt;client I wrote&lt;/a&gt; to talk to &lt;a href="http://www.smitegame.com/" class="external-link" target="_blank" rel="noopener"&gt;Smite’s&lt;/a&gt; API.&lt;/p&gt;
&lt;h1 id="directly-use-the-struct"&gt;
 Directly use the struct
 &lt;a class="heading-link" href="#directly-use-the-struct"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;Link to heading&lt;/span&gt;
 &lt;/a&gt;
&lt;/h1&gt;
&lt;p&gt;While constructor functions are sometimes needed for Go libraries, it’s strongly preferred to support users directly
using your struct{} object. For example, the Go standard library’s http client is used by directly instantiating it.
The advantages of direct struct initialization vs constructor functions is worthy of its own post, but the primary
reasons are local clarity and simplicity of code.&lt;/p&gt;</description></item><item><title>Repository organization tips in Go</title><link>https://cep.dev/posts/repository-organization-tips-in-go/</link><pubDate>Mon, 27 Jun 2016 22:39:42 +0000</pubDate><guid>https://cep.dev/posts/repository-organization-tips-in-go/</guid><description>&lt;p&gt;This post will describe common approaches to organizing Go code into packages and what I feel is the ideal directory
structure for Go repositories. Before starting with this post, it may be useful to also read
&lt;a href="https://blog.golang.org/package-names" class="external-link" target="_blank" rel="noopener"&gt;https://blog.golang.org/package-names&lt;/a&gt; first for context.&lt;/p&gt;
&lt;h1 id="a-setup-with-package-proliferation"&gt;
 A setup with package proliferation
 &lt;a class="heading-link" href="#a-setup-with-package-proliferation"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;Link to heading&lt;/span&gt;
 &lt;/a&gt;
&lt;/h1&gt;
&lt;p&gt;Let’s take an example application called gatekeeper. It may have a public client that other programs use to connect to
it and may have parts around authentication and payment, used by gatekeeper internally. One structure is like the
following.&lt;/p&gt;</description></item><item><title>Preemptive Interface Anti-Pattern in Go</title><link>https://cep.dev/posts/preemptive-interface-antipattern-in-go/</link><pubDate>Thu, 23 Jun 2016 22:47:58 +0000</pubDate><guid>https://cep.dev/posts/preemptive-interface-antipattern-in-go/</guid><description>&lt;p&gt;In this post I will describe the Preemptive Interface pattern often used in code and why I think it is generally an
incorrect pattern to follow in Go.&lt;/p&gt;
&lt;h1 id="what-is-a-preemptive-interface"&gt;
 What is a Preemptive Interface
 &lt;a class="heading-link" href="#what-is-a-preemptive-interface"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;Link to heading&lt;/span&gt;
 &lt;/a&gt;
&lt;/h1&gt;
&lt;p&gt;Interfaces are a way to describe behavior and exist in most typed languages. Preemptive interfaces are when a developer
codes to an interface before an &lt;strong&gt;actual&lt;/strong&gt; need arrises. An example may look like the following.&lt;/p&gt;</description></item></channel></rss>