Dotfile stewardship for the indolent

I’m one of those people who will sit in front of a computer for hours, fiddling with algorithms or debugging performance issues, yet won’t spend 10 minutes to improve their workflows. While I usually get away with this, every now and then, my inertia slithers back to bite me. The latest episode was me realizing how tedious it is to move config files across multiple devices when I was configuring a new MacBook Air and Mac Mini at the same time....

September 27, 2023

An ode to the neo-grotesque web

Every once in a while, I love browsing the Wayback Machine1 to catch a glimpse of the early internet. I enjoy the waves of nostalgic indie hacker vibes that wash over me as I type a URL into the search box and click to see an old snapshot of the site frozen in time. Being a kid of the early ’00s, I missed the spectacular cosmic genesis of the ’90s internet in its entire nascent glory....

September 18, 2023

Self-hosted Google Fonts in Hugo

This site1 is built with Hugo2 and served via GitHub pages3. Recently, I decided to change the font here to make things more consistent across different devices. However, I didn’t want to go with Google Fonts for a few reasons: CDN is another dependency. Hosting static assets on GitHub Pages has served me well. Google Fonts tracks users and violates4 GDPR in Germany. Google Analytics does that too. But since I’m using the latter anyway, this might come off a bit apocryphal....

September 14, 2023

Configuring options in Go

Suppose, you have a function that takes an option struct and a message as input. Then it stylizes the message according to the option fields and prints it. What’s the most sensible API you can offer for users to configure your function? Observe: // app/src package src // Option struct type Style struct { Fg string // ANSI escape codes for foreground color Bg string // Background color } // Display the message according to Style func Display(s *Style, msg string) {} In the src package, the function Display takes a pointer to a Style instance and a msg string as parameters....

September 5, 2023

Dummy load balancer in a single Go script

I was curious to see if I could prototype a simple load balancer in a single Go script. Go’s standard library and goroutines make this trivial. Here’s what the script needs to do: Spin up two backend servers that’ll handle the incoming requests. Run a reverse proxy load balancer in the foreground. The load balancer will accept client connections and round-robin them to one of the backend servers; balancing the inbound load....

August 30, 2023

Limit goroutines with buffered channels

I was cobbling together a long-running Go script to send webhook messages to a system when some events occur. The initial script would continuously poll a Kafka topic for events and spawn new goroutines to make HTTP requests to the destination. This had two problems: It could create unlimited goroutines if many events arrived quickly It might overload the destination system by making many concurrent requests In Python, I’d use just asyncio....

August 23, 2023

Writing a TOTP client in Go

A TOTP1 based 2FA system has two parts. One is a client that generates the TOTP code. The other part is a server. The server verifies the code. If the client and the server-generated codes match, the server allows the inbound user to access the target system. The code usually expires after 30 seconds and then, you’ll have to regenerate it to be able to authenticate. As per RFC-62382, the server shares a base-32 encoded secret key with the client....

August 20, 2023

Interface guards in Go

I love Go’s implicit interfaces. While convenient, they can also introduce subtle bugs unless you’re careful. Types expected to conform to certain interfaces can fluidly add or remove methods. The compiler will only complain if an identifier anticipates an interface, but is passed a type that doesn’t implement that interface. This can be problematic if you need to export types that are required to implement specific interfaces as part of their API contract....

August 18, 2023

Writing on well-trodden topics

I enjoy writing about software—the things I learn, the tools I use, and the work I do. Owing to the constraints of the corporate software world, more often than not, you can’t showcase your work or talk about them. At least that’s how it always has been throughout my career. At the same time, as you grow older and start having a life outside of the computer screen, you realize that working on OSS at the tail of a 40+ hour workweek is hard, and maintaining consistency is even harder....

August 14, 2023

Go structured logging with slog

Before the release of version 1.21, you couldn’t set levels for your log messages in Go without either using third-party libraries or writing your own boilerplates. Coming from Python, I’ve always found this odd, considering that this capability has been in the Python standard library forever. However, it seems like the new log/slog subpackage in Go allows you to do that and a whole lot more. Apart from being able to add levels to log messages, slog also allows you to emit JSON-structured log messages and group them by certain attributes....

August 10, 2023

Notes on exit interviews

If you’re a manager, then there’s no shortage of information for you on how to conduct exit interviews. But there aren’t many resources that focus on how to handle them from an employee’s perspective. I’ve been meaning to write a quick piece that isn’t biased by anyone else’s experience and is short enough so that I can quickly jog my memory in the future should the need arise. While I’ve participated in a few of them over the past five years, this text doesn’t attempt to combat the inexorable recency bias that may have seeped into the writing....

August 7, 2023

Taming conditionals with bitmasks

The 100k context window of Claude 21 has been a huge boon for me since now I can paste a moderately complex problem to the chat window and ask questions about it. In that spirit, it recently refactored some pretty gnarly conditional logic for me in such an elegant manner that it absolutely blew me away. Now, I know how bitmasks2 work and am aware of the existence of enum.Flag3 in Python....

July 29, 2023

Using DNS record to share text data

This morning, while browsing Hacker News, I came across a neat trick1 that allows you to share textual data by leveraging DNS TXT records. It can be useful for sharing a small amount of data in environments that restrict IP but allow DNS queries, or to bypass censorship. To test this out, I opened my domain registrar’s panel and created a new TXT type DNS entry with a base64 encoded message containing the poem A Poison Tree by William Blake....

July 17, 2023

Memory leakage in Python descriptors

Unless I’m hand rolling my own ORM-like feature or validation logic, I rarely need to write custom descriptors in Python. The built-in descriptor magics like @classmethod, @property, @staticmethod, and vanilla instance methods usually get the job done. However, every time I need to dig my teeth into descriptors, I reach for this fantastic how to1 guide by Raymond Hettinger. You should definitely set aside the time to read it if you haven’t already....

July 16, 2023

Unix-style pipelining with Python's subprocess module

Python offers a ton of ways like os.system or os.spawn* to create new processes and run arbitrary commands in your system. However, the documentation usually encourages you to use the subprocess1 module for creating and managing child processes. The subprocess module exposes a high-level run() function that provides a simple interface for running a subprocess and waiting for it to complete. It accepts the command to run as a list of strings, starts the subprocess, waits for it to finish, and then returns a CompletedProcess object with information about the result....

July 14, 2023

Enabling repeatable lazy iterations in Python

The current title of this post is probably incorrect and may even be misleading. I had a hard time coming up with a suitable name for it. But the idea goes like this: sometimes you might find yourself in a situation where you need to iterate through a generator more than once. Sure, you can use an iterable like a tuple or list to allow multiple iterations, but if the number of elements is large, that’ll cause an OOM error....

July 13, 2023

Descending into the aether

Around a year ago, I ditched my fancy Linux rig for a beefed-up 16" MacBook Pro and ever since, it’s been my primary machine for both personal and work stuff. I love how this machine strikes a decent balance between power and portability. However, I often joke that this chonky boy is just a pound shy of being an ENIAC1. It’s a beast of a machine when you need all that power, but certainly isn’t the most convenient contraption to lug around while flying....

July 9, 2023

Escaping the template pattern hellscape in Python

Over the years, I’ve used the template pattern1 across multiple OO languages with varying degrees of success. It was one of the first patterns I learned in the primordial hours of my software engineering career, and for some reason, it just feels like the natural way to tackle many real-world code-sharing problems. Yet, even before I jumped on board with the composition over inheritance2 camp, I couldn’t help but notice how using this particular inheritance technique spawns all sorts of design and maintenance headaches as the codebase starts to grow....

July 1, 2023

Python dependency management redux

One major drawback of Python’s huge ecosystem is the significant variances in workflows among people trying to accomplish different things. This holds true for dependency management as well. Depending on what you’re doing with Python—whether it’s building reusable libraries, writing web apps, or diving into data science and machine learning—your workflow can look completely different from someone else’s. That being said, my usual approach to any development process is to pick a method and give it a shot to see if it works for my specific needs....

June 27, 2023

Implementing a simple traceroute clone in Python

I was watching this amazing lightning talk1 by Karla Burnett and wanted to understand how traceroute works in Unix. Traceroute is a tool that shows the route of a network packet from your computer to another computer on the internet. It also tells you how long it takes for the packet to reach each stop along the way. It’s useful when you want to know more about how your computer connects to other computers on the internet....

June 1, 2023