Skip to content

Writing

RSS

Posts and articles I've written.

Preventing database connection leaks

A handler that raises on some inputs leaks one database connection per failing request. After thirty of those, the pool is empty and healthy requests start dying with timeouts. Why cleanup belongs in finally, and where to put it so nobody has to remember.

2 min read
  • databases
  • python
  • backend
Databases in production

A new series with a different format: short posts, one database practice each, all pulled from things that actually break under load. Connection leaks, invisible N+1s, migrations that lock tables, tasks that run against data that does not exist yet.

1 min read
  • databases
  • python
  • backend
Dependency maintenance on autopilot with Renovate

Part 12's scanners tell you which dependencies are vulnerable; someone still has to upgrade them. Self-hosted Renovate as a scheduled CI job, the two tokens that keep it alive, and the pre-flight check that turned a recurring debugging session into a one-line log read.

5 min read
  • gitlab
  • ci-cd
  • devops
Security scanning nobody ignores

The managed security scan takes 21 minutes, floods every merge request with findings about code nobody touched, and the team learns to scroll past it. Diff-aware SAST with Semgrep, a severity gate for OSV-Scanner, and the report format that puts findings back in the MR widget.

6 min read
  • gitlab
  • ci-cd
  • security
Scheduled pipelines and E2E: signal without blocking

The E2E suite is too slow and too flaky to gate merges, but you still need the signal, and a place to see its history. Scheduled pipelines, service tokens for a gated environment, Playwright sharding, and a report hub that outlives its pipelines.

6 min read
  • gitlab
  • ci-cd
  • devops
Releasing from CI without retriggering yourself

A release job that pushes a version-bump commit triggers a new pipeline, and two merges landing close together race each other to npm. Serializing releases with resource_group, authenticating the push, and the difference between [skip ci] and -o ci.skip.

5 min read
  • gitlab
  • ci-cd
  • devops
Monorepo pipelines in GitLab CI: selective everything

Fifty packages and eight apps in one repo means rebuilding the world on every commit is not an option. Change detection with rules:changes and compare_to, one YAML anchor per app, a task runner that already knows the dependency graph, and the week the runners ran out of disk.

6 min read
  • gitlab
  • ci-cd
  • devops
A shared CI library: one pipeline config for ten repos

Ten sibling repos copy-pasted the same 300 lines of pipeline YAML and every copy drifted in its own direction. include:, hidden jobs as a public API, a !reference rules vocabulary, and how to ship changes when every consumer tracks main.

7 min read
  • gitlab
  • ci-cd
  • devops
Downstream pipelines: making repos talk to each other

Merging a frontend change should run E2E tests that live in a different repo, owned by a different team. Trigger jobs, multi-project vs parent-child pipelines, mirroring the downstream status, and a variables allowlist that doubles as a secret boundary.

6 min read
  • gitlab
  • ci-cd
  • devops
Workflow and pipeline types in GitLab CI: one pipeline per commit

Push a branch that has an open merge request and you get two pipelines for the same commit: double the cost, two statuses to read. Pipeline types, workflow rules as the gatekeeper, and what running branch-only pipelines actually costs.

6 min read
  • gitlab
  • ci-cd
  • devops
Rules in GitLab CI: controlling when jobs run

Every job runs on every push: deploy jobs tag along on feature branches, and expensive suites run when nothing relevant changed. Job-level rules (if, changes, exists), manual gates, and a regex that silently matched almost every commit message.

5 min read
  • gitlab
  • ci-cd
  • devops
Faster GitLab CI pipelines with needs and parallel

Your jobs are efficient but your pipeline is slow, because stages make every job wait for jobs it does not depend on. Replacing stage barriers with a needs graph, and splitting the slowest job across runners with parallel.

3 min read
  • gitlab
  • ci-cd
  • devops
Artifacts in GitLab CI: build once, reuse everywhere

Your deploy job rebuilds the app that another job just built. Caching dist/ seems to fix it, until it silently deploys stale code. Artifacts, expiry, failure reports, and passing computed values between jobs with dotenv.

3 min read
  • gitlab
  • ci-cd
  • devops
Cache policies in GitLab CI: pull, push, and fallback keys

A working cache still wastes time in three ways: every job re-uploads it, a lockfile bump starts from zero, and merge requests never see what main warmed up. Cache policies, fallback keys, and the protected-branch split.

3 min read
  • gitlab
  • ci-cd
  • devops
How to write a custom ESLint rule

Building a custom ESLint rule that bans a component, with a walk through traversing the AST, picking the right node type, and bundling the rule into a local plugin.

4 min read
  • javascript
  • eslint
  • tooling
How to upload files to S3 using @aws-sdk/client-s3

Using @aws-sdk/client-s3 from Node.js to upload single files and entire folders to AWS S3, plus the gotchas you only learn the hard way (content type, leading slashes, Windows paths).

4 min read
  • javascript
  • node.js
  • aws
  • aws-s3
  • tooling
How to clamp text to N lines with CSS

A pure-CSS recipe for limiting a block of text to a fixed number of lines: handy when the content is dynamic and you don't want the layout to drift.

1 min read
  • css
  • snippets
How to integrate NProgress with Next.js

Snippets for showing a top loading bar while Next.js navigates between pages, using NProgress wired to the Pages Router events.

1 min read
  • react
  • next.js
  • snippets
GORM cheatsheet for Go

A handful of GORM snippets I keep around when I start a project in Go: installing, modeling, validations, many-to-many relations, hooks, and the queries I run most often.

2 min read
  • go
  • gorm
  • snippets
Being Tech at Crehana: fail, but learn fast

What I learned in my first three years as a Frontend Developer at Crehana: failing fast, believing in what you build, and why people matter more than anything else.

3 min read
  • culture
  • career
  • crehana
BDD in Ruby on Rails with RSpec and Capybara

Why controller specs often re-test what Rails already guarantees, and how feature tests with RSpec and Capybara let you test what the user actually sees.

5 min read
  • ruby
  • rails
  • testing
  • bdd
How to test your Rails models with RSpec

An introduction to TDD in Ruby on Rails; the red-green-refactor cycle and how to test a model's validations with RSpec.

6 min read
  • ruby
  • rails
  • testing
  • tdd