Secrets Management in the Modern Stack

We’ve all done it. Committed an API key to git. Hardcoded a database password “just for testing.” Posted a screenshot with credentials visible in the corner. The security community has a name for this: Tuesday. But secrets management doesn’t have to be painful. Let’s walk through the progression from “please no” to “actually reasonable” in handling sensitive credentials. The Hierarchy of Secrets (From Worst to Best) Level 0: Hardcoded in Source 1 2 3 # Don't do this. Ever. db_password = "hunter2" api_key = "sk-live-definitely-real-key" This is how breaches happen. Credentials in source code get committed to git, pushed to GitHub, indexed by bots within minutes, and suddenly someone’s mining crypto on your AWS account. ...

February 24, 2026 Â· 5 min Â· 969 words Â· Rob Washington

DNS for Developers: Understanding the Internet's Phone Book

DNS is invisible until it breaks. Then everything breaks. Understanding how DNS works helps you debug issues faster and configure services correctly. The Basics DNS translates human-readable names to IP addresses: e x a m p l e . c o m → 9 3 . 1 8 4 . 2 1 6 . 3 4 The resolution process: 1 2 3 4 5 . . . . . B O Q R A r S u e n o e s s w c r o w s h y l e e e v r r c g e k o r c c s e a h s q c e i u h c t t e e k s o r d s i c c e a l a o s t o c n c h f r e a e i o a l g o c u t h c r a e s l c d e e h r v e r v e e e l s r o s b l a v → s e e r T d L ( D o e n . s g e T . r T , v L e 8 r . s 8 . → 8 . a 8 u ) t h o r i t a t i v e s e r v e r s Record Types A Record (IPv4 Address) e x a m p l e . c o m . 3 0 0 I N A 9 3 . 1 8 4 . 2 1 6 . 3 4 Maps a name to an IPv4 address. ...

February 24, 2026 Â· 11 min Â· 2168 words Â· Rob Washington

Redis Patterns: Beyond Simple Caching

Redis gets introduced as a cache, but that undersells it. It’s an in-memory data structure server with atomic operations, pub/sub, streams, and more. These patterns show Redis’s real power. Basic Caching (The Familiar One) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import redis import json r = redis.Redis(host='localhost', port=6379, decode_responses=True) def get_user(user_id): # Check cache first cached = r.get(f"user:{user_id}") if cached: return json.loads(cached) # Miss: fetch from database user = db.query("SELECT * FROM users WHERE id = %s", user_id) # Cache with TTL r.setex(f"user:{user_id}", 3600, json.dumps(user)) return user Rate Limiting Sliding window rate limiter with sorted sets: ...

February 23, 2026 Â· 5 min Â· 1055 words Â· Rob Washington

Nginx Configuration Patterns: From Basic Proxy to Production-Ready

Nginx is everywhere: reverse proxy, load balancer, static file server, SSL terminator. Its configuration syntax is powerful but has gotchas that catch everyone at least once. These patterns cover common use cases done right. Basic Reverse Proxy 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 upstream backend { server 127.0.0.1:3000; } server { listen 80; server_name example.com; location / { proxy_pass http://backend; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } } Always set those headers — your backend needs to know the real client IP and protocol. ...

February 23, 2026 Â· 5 min Â· 1043 words Â· Rob Washington

Secrets Management Patterns for Modern Infrastructure

Every infrastructure team eventually faces the same uncomfortable question: where do the secrets go? API keys, database passwords, TLS certificates, OAuth tokens — they all need to live somewhere. The wrong answer (“in the repo, it’s fine, it’s private”) creates technical debt that compounds silently until someone accidentally pushes to public or an ex-employee still has access to production credentials. The Anti-Patterns First Environment variables everywhere. Yes, the twelve-factor app says config comes from the environment. But “the environment” doesn’t mean a .env file committed to git. Environment variables are runtime config, not secret storage. ...

February 23, 2026 Â· 4 min Â· 709 words Â· Rob Washington

Systemd Service Management: Running Applications Reliably

Systemd is how modern Linux manages services. It starts your applications at boot, restarts them when they crash, and handles dependencies between services. Understanding systemd transforms “it works when I run it manually” into “it runs reliably in production.” Basic Service Unit 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 # /etc/systemd/system/myapp.service [Unit] Description=My Application After=network.target [Service] Type=simple User=appuser WorkingDirectory=/opt/myapp ExecStart=/opt/myapp/bin/server Restart=always RestartSec=5 [Install] WantedBy=multi-user.target 1 2 3 4 # Enable and start sudo systemctl daemon-reload sudo systemctl enable myapp sudo systemctl start myapp Service Types simple (default): Process started by ExecStart is the main process. ...

February 23, 2026 Â· 5 min Â· 915 words Â· Rob Washington

Backup Strategies: Because Hope Is Not a Disaster Recovery Plan

Everyone has backups. Few have tested restores. The backup that fails during a crisis is worse than no backup — it gave you false confidence. Backup strategy isn’t about the backup. It’s about the restore. The 3-2-1 Rule A minimum viable backup strategy: 3 copies of your data 2 different storage media/types 1 copy offsite P C C C r o o o i p p p m y y y a r 1 2 3 y : : : : P L R O r o e f o c m f d a o s u l t i c e t t s e i n r o a e a n p p r s l c d h i h a o c i t t a v a e b ( ( a s d ( s a i d e m f i e f f e f d r e a e r t n e a t n c t e r n e p t g r e i o r o v ) n i ) d e r ) What to Back Up Always: ...

February 23, 2026 Â· 6 min Â· 1110 words Â· Rob Washington

Ansible Playbook Patterns: Writing Automation That Doesn't Break

Ansible’s simplicity is seductive. YAML tasks, SSH connections, no agents. But simple playbooks become complex fast, and poorly structured automation creates more problems than it solves. These patterns help you write Ansible that scales with your infrastructure. Idempotency: Safe to Run Twice Every task should be safe to run repeatedly with the same result: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 # Idempotent - creates file if missing, no-op if exists - name: Create config directory file: path: /etc/myapp state: directory mode: '0755' # Not idempotent - appends every run - name: Add config line shell: echo "setting=value" >> /etc/myapp/config # Idempotent version - name: Add config line lineinfile: path: /etc/myapp/config line: "setting=value" Use Ansible modules over shell commands. Modules are designed for idempotency. ...

February 23, 2026 Â· 6 min Â· 1235 words Â· Rob Washington

Kubernetes Resource Management: Requests, Limits, and Not Getting OOMKilled

Kubernetes needs to know how much CPU and memory your containers need. Get it wrong and you’ll face OOMKills, CPU throttling, unschedulable pods, or wasted cluster capacity. Resource requests and limits are the most impactful settings most teams misconfigure. Requests vs Limits Requests: What you’re guaranteed. Used for scheduling. Limits: What you can’t exceed. Enforced at runtime. 1 2 3 4 5 6 7 resources: requests: memory: "256Mi" cpu: "250m" limits: memory: "512Mi" cpu: "500m" This pod: ...

February 23, 2026 Â· 5 min Â· 944 words Â· Rob Washington

CI/CD Pipelines: From Commit to Production Safely

Continuous Integration and Continuous Deployment transform code changes into running software automatically. Done well, you push code and forget about it — the pipeline handles testing, building, and deploying. Done poorly, you spend more time fighting the pipeline than writing code. The Pipeline Stages C o m m i t → B u i l d → T e s t → S e c u r i t y → A r t i f a c t → D e p l o y → V e r i f y Each stage is a gate. Fail any stage, stop the pipeline. ...

February 23, 2026 Â· 6 min Â· 1182 words Â· Rob Washington