diff --git a/README.md b/README.md index fc4bf69..a2371bb 100644 --- a/README.md +++ b/README.md @@ -4,10 +4,13 @@ Personal portfolio site. Hand-coded, no frameworks, no build step. ## πŸ—‚ What's in here -- **`index.html`** β€” home (work, writing, glyph strip) +- **`index.html`** β€” home - **`about.html`** β€” who I am, stack, CV +- **`uses.html`** β€” tools/gear +- **`projects/`** β€” repos + open source contributions - **`writing/`** β€” blog posts -- **`assets/`** β€” CV + anything else +- **`work/`** β€” engineering impact case studies +- **`assets/`** β€” CV + everything else ## πŸ›  Stack diff --git a/about.html b/about.html index f3212be..b1bb288 100644 --- a/about.html +++ b/about.html @@ -3,320 +3,419 @@ - About β€” Ausb - - - + About β€” Austin Edmonson - - - + .footer-links a:hover { + color: var(--ink); + } + + @media (min-width: 900px) { + main { + max-width: 980px; + display: grid; + grid-template-columns: 1fr 380px; + column-gap: 64px; + row-gap: 0; + align-items: start; + grid-template-areas: + "headline photo" + "bio photo" + "howiwork connect"; + } -
- - - -
+ .about-hero { + display: contents; + } -
-

Austin Edmonson

-

Platform engineer Β· DevOps Β· software builder

-
+ .about-headline { + grid-area: headline; + flex: initial; + order: initial; + } -
-
+ .about-avatar { + grid-area: photo; + order: initial; + width: 100%; + height: auto; + aspect-ratio: 1 / 1; + border-radius: 20px; + } -
- Currently - Platform Engineering Β· The Home Depot -
+ html.dark-mode .about-avatar { + border: none; + } -
- Building - Partida β€” immigration tech for families -
+ .about-bio { + grid-area: bio; + } -
- Stack - K8s Β· Terraform Β· Python Β· Docker Β· FastAPI -
+ .how-i-work { + grid-area: howiwork; + } -
- AI - Claude Β· Claude Code Β· GitHub Copilot Β· ChatGPT -
+ .connect { + grid-area: connect; + margin-top: 0; + align-self: start; + } + } + + + -
- GitHub - ausbernard β†— +
+
+
+ + + +
+
+ Austin Edmonson
-
- CV - Download β†— + +
+ +
+
+

I'm Austin. I build internal platforms that make thousands of engineers faster.

+ Austin Edmonson +
+

6+ years across DevOps, platform engineering, and software engineering. Self-taught but not self-made. I have benefitted from working with brilliant engineers and managers throughout my career - and learning alongside them. I collaborate across teams exceptionally well and I thrive in ambiguity and drive results. Started as a DevOps intern at Shadow Soft, moved into a Systems Engineer role at Acoustic AI, then joined The Home Depot, where I now own end-to-end CI/CD pipeline architecture for a 3,000+ developer organization. Alongside that, I'm the sole founder and developer of Partida, an immigration case management platform for families relocating to Portugal.

+ +
+ +
    +
  • Self-taught, by necessity. I'm good at finding the right resource, making sense of it fast, and turning unclear problems into working systems.
  • +
  • AI as a multiplier, not a shortcut. Claude and Copilot compress the time it takes to get from ambiguity to clarity β€” the engineering judgment still has to be mine.
  • +
  • Ship it safely, then sharpen it. I don't live by "good enough." I want things done quickly, thoroughly, safely.
  • +
  • Write it down. If I learned it the hard way, I write about it so someone else doesn't have to.
  • +
+
+ +
+ + +
+
+ +
+ -
-

I grew up on MySpace and fixing my parents' computer. Self-taught from the start β€” which came with some low confidence early on β€” but every road I tried eventually curved back to computers and Python.

-

Being self-taught made me good at one thing above everything else: finding the right resource, making sense of it fast, and turning unclear problems into working systems.

-

Today, that process is accelerated by AI tools like Claude, Copilot, and ChatGPTβ€”not as shortcuts, but as part of how I explore system design, validate implementation paths, and move faster from ambiguity to clarity. I still rely on hands-on engineering to ground everything in real constraints, but AI helps me compress the time it takes to get there.

-

Over 6+ years across DevOps, platform engineering, and software engineering, I've built CI/CD workflows at The Home Depot responsible for building, scanning, testing, and deploying into Kubernetes infrastructure. I've led efforts to simplify Terraform-heavy operational workflows, and built Grafana dashboards that turned noisy systems into something teams could actually reason about.

-

Whether it's a SaaS integration or my own product, I don't live by "good enough." I want things done quickly, thoroughly, safely β€” and with some pizzaz. That's the standard I hold for everything I touch.

-
+ + diff --git a/assets/acoustic-ai-logo.jpeg b/assets/acoustic-ai-logo.jpeg new file mode 100644 index 0000000..e43cc3b Binary files /dev/null and b/assets/acoustic-ai-logo.jpeg differ diff --git a/assets/austin-headshot.jpeg b/assets/austin-headshot.jpeg new file mode 100644 index 0000000..f1c38ee Binary files /dev/null and b/assets/austin-headshot.jpeg differ diff --git a/assets/cairn-cover.jpg b/assets/cairn-cover.jpg new file mode 100644 index 0000000..0f3c85c Binary files /dev/null and b/assets/cairn-cover.jpg differ diff --git a/assets/cicd-every-team.png b/assets/cicd-every-team.png new file mode 100644 index 0000000..8af0c73 Binary files /dev/null and b/assets/cicd-every-team.png differ diff --git a/assets/cicd-same-image-hero.jpg b/assets/cicd-same-image-hero.jpg new file mode 100644 index 0000000..a309af6 Binary files /dev/null and b/assets/cicd-same-image-hero.jpg differ diff --git a/assets/github-actions-runner.jpg b/assets/github-actions-runner.jpg new file mode 100644 index 0000000..49f3f3f Binary files /dev/null and b/assets/github-actions-runner.jpg differ diff --git a/assets/home-depot-logo.png b/assets/home-depot-logo.png new file mode 100644 index 0000000..768d9b0 Binary files /dev/null and b/assets/home-depot-logo.png differ diff --git a/assets/llm-non-determinism-hero.jpg b/assets/llm-non-determinism-hero.jpg new file mode 100644 index 0000000..1a63581 Binary files /dev/null and b/assets/llm-non-determinism-hero.jpg differ diff --git a/assets/overengineering-hero.jpg b/assets/overengineering-hero.jpg new file mode 100644 index 0000000..6c13ab3 Binary files /dev/null and b/assets/overengineering-hero.jpg differ diff --git a/assets/partida-technical-breakdown-hero.jpg b/assets/partida-technical-breakdown-hero.jpg new file mode 100644 index 0000000..9cbf8e8 Binary files /dev/null and b/assets/partida-technical-breakdown-hero.jpg differ diff --git a/assets/python-ci-pavedroad-cover.jpg b/assets/python-ci-pavedroad-cover.jpg new file mode 100644 index 0000000..86a6d68 Binary files /dev/null and b/assets/python-ci-pavedroad-cover.jpg differ diff --git a/assets/shadow-soft-logo.png b/assets/shadow-soft-logo.png new file mode 100644 index 0000000..daf105d Binary files /dev/null and b/assets/shadow-soft-logo.png differ diff --git a/assets/vigia-cover.jpg b/assets/vigia-cover.jpg new file mode 100644 index 0000000..7f14d69 Binary files /dev/null and b/assets/vigia-cover.jpg differ diff --git a/index.html b/index.html index 6ea6c0e..556f232 100644 --- a/index.html +++ b/index.html @@ -4,1020 +4,549 @@ Ausb - - - - - -
-

Software & Platform Engineer

-

I build production systems from zero.

-

I build backend systems, cloud infrastructure, and the tooling that keeps teams shipping. Remote-first and timezone flexible.

-
- See work β†’ - Download resume + + + +
+ Austin Edmonson +

I build internal platforms that make thousands of engineers faster.

+

Senior Platform Engineer focused on developer experience, CI/CD, Kubernetes, and AI-assisted software delivery.

+

I design systems that remove friction from the software development lifecycle so engineering teams can ship software faster, safer, and with more confidence.

+ + -
-
-
- -
- - -
- - - - - - - - - - - - -
- - -
- - - - - - - - - - - -
- - -
- - - - - - -
- - -
- - - - - -
- -
- -
-

Work

- -
-

Product Β· Design Β· Platform

-

Partida

-

Immigration tech built for families, not lawyers. Product, design, and platform engineering from zero.

- -
-
- -
-
-

Product Impact

-
    -
  • 15 families onboarded to beta
  • -
  • 2 attorney partners providing feedback
  • -
  • Document tracking across 19 case types
  • -
-
- -
-

Platform Engineering

-
    -
  • 12 deploys/week on Railway
  • -
  • FastAPI + SQLAlchemy async, PostgreSQL
  • -
  • Firebase Auth + GCP Cloud Storage (compliance-first)
  • -
  • HTMX + Jinja2 for progressive enhancement
  • -
-
- -
-

AI-Augmented Development

-
    -
  • Claude for architecture design & code review
  • -
  • 40% faster feature iteration with AI-assisted testing
  • -
  • Real-time schema migration planning
  • -
-
- - +
+ +
+
+ +
+
+ - -
-

Tech Stack

-
-

Backend

-

FastAPI, SQLAlchemy

+
+
+

The Home Depot

+

Senior Software Engineer

-
-

Database

-

PostgreSQL async

-
-
-

Frontend

-

HTMX, Jinja2

-
-
-

Auth

-

Firebase Auth

+ 2025 β€” Present +
+
+
+ +
+
+

The Home Depot

+

Software Engineer I & II

-
-

Hosting

-

Railway, PostgreSQL

+ 2022 β€” 2025 +
+
+
+ +
+
+

Acoustic AI

+

Systems Engineer

-
-

Role

-

Solo founder, all layers

+ 2020 +
+
+
+ +
+
+

Shadow Soft

+

DevOps Intern

+ 2019 β€” 2020
-
-
- -
- -
-
-

Writing

- All posts β†’ -
- - - -
- -
-

Open Source Contributions

- - - confidence-sdk-python -
-

Found shared mutable class-level context causing instance data leakage

-

All Confidence instances shared the same class-level context dict β€” setting context on one silently contaminated all others. Identified the root cause, proposed moving initialization to __init__, and flagged a secondary risk with a shared httpx.AsyncClient.

- Closed β†— -
- - - gocardless-pro-python -
-

Fixed rate_limit returning a dict instead of a RateLimit object

-

The public Client.rate_limit property broke documented attribute access (.limit, .remaining, .reset). Identified the gap between the internal API layer and the public interface, wrote a failing test, and submitted the fix.

-
- Closed β†— -
- - - gocardless-pro-python -
-

Added direct unit tests for the Paginator class

-

The Paginator class powers every .all() call in the library but had zero direct coverage. Added 7 isolated unit tests with unittest.mock covering multi-page traversal, cursor logic, parameter passing, empty responses, and mutation safety.

-
- Closed β†— -
+
+ - + + diff --git a/projects/index.html b/projects/index.html new file mode 100644 index 0000000..05284ae --- /dev/null +++ b/projects/index.html @@ -0,0 +1,426 @@ + + + + + + Projects β€” Austin Edmonson + + + + +
+
+
+ + + +
+
+ Austin Edmonson +
+ + +
+ +
+

Projects

+

Things I've built, plus open source contributions along the way.

+ +
+ + +
+ +
+ + +
+
+ + + + + + + diff --git a/recruit.html b/recruit.html deleted file mode 100644 index 0e6397d..0000000 --- a/recruit.html +++ /dev/null @@ -1,719 +0,0 @@ - - - - - - Recruit β€” Ausb - - - - - - - - - -
-

Let's talk shop.

-

A terminal felt more honest than a form. Start with help.

-
- -
-
-
- austin@portfolio ~ % - -
-
-
- ❯ -
- - -
-
-
- - - - diff --git a/uses.html b/uses.html new file mode 100644 index 0000000..1eba488 --- /dev/null +++ b/uses.html @@ -0,0 +1,313 @@ + + + + + + Uses β€” Austin Edmonson + + + + +
+
+
+ + + +
+
+ Austin Edmonson +
+ + +
+ +
+

Tools I Actually Use.

+

I prefer fewer, better tools over a sprawling stack. Every item on this list earned its spot by surviving real work. I update my technology when they are outgrown, not when something shiny comes up.

+ +
+ +
+
+

15" MacBook Pro (2019)

+

Primary machine.

+
+
+

Thinkpad T420

+

Linux workhorse.

+
+
+

11" iPad Pro with Apple Pencil

+

Thinking and sketching device.

+
+
+

Yoga Ball

+

Ergonomic seating.

+
+
+
+ +
+ +
+
+

Cursor

+

Primary editor with AI integration.

+
+
+

VS Code

+

Language-specific IDEs.

+
+
+
+ +
+ +
+
+

Claude and Claude Code

+

Primary AI pair.

+
+
+

Deepseek

+

Hard-nosed techincal tutor.

+
+
+
+ +
+ +
+
+

Obsidian

+

Note-taking and planning.

+
+
+

Tldraw

+

Whiteboard.

+
+
+
+ +
+ +
+
+

Notion

+

Task and project management.

+
+
+

Cairn

+

Session sized planning.

+
+
+
+
+ + + + + diff --git a/work/ai-developer-workflows.html b/work/ai-developer-workflows.html new file mode 100644 index 0000000..a5a3934 --- /dev/null +++ b/work/ai-developer-workflows.html @@ -0,0 +1,292 @@ + + + + + + AI Developer Workflows β€” Austin Edmonson + + + + +
+
+
+ + + +
+
+ Austin Edmonson +
+ + +
+ +
+ ← +

AI Developer Workflows

+ +
+ +

...

+
+ +
+ +

...

+
+ +
+ +
    +
  • ...
  • +
+
+ +
+ +

...

+

...

+
+ +
+ +

What I'd change...

+

Tradeoffs...

+

Architecture...

+
+
+ + + + + diff --git a/work/cicd-platform.html b/work/cicd-platform.html new file mode 100644 index 0000000..bcb5a8f --- /dev/null +++ b/work/cicd-platform.html @@ -0,0 +1,437 @@ + + + + + + CI/CD Platform β€” Austin Edmonson + + + + +
+
+
+ + + +
+
+ Austin Edmonson +
+ + +
+ +
+ ← +

CI/CD Platform

+ + Every team built pipelines differently β€” TeamCity, Concourse, Jenkins, and GitHub Actions, with fragmented maintainability, inconsistent onboarding, and minimal visibility into production. + +
+ +

3,000+ engineers. 300,000+ repositories. No standard way to ship code.

+

Every team built pipelines differently β€” TeamCity, Concourse, Jenkins, GitHub Actions.

+

Maintainability and costs were fragmented across different teams.

+

Developer onboarding to these tools was inconsistent.

+

We had no idea, as a body, where the code going to production was scanned, tested, and through which means. Visibility was minimal.

+
+ +
+ +

We interviewed engineering teams across the organization to understand how software was being built and deployed.

+

We documented common workflows, identified shared tooling, and looked for opportunities to standardize the developer experience.

+

We found that nearly every team followed the same core workflow:

+
    +
  • Install dependencies
  • +
  • Build
  • +
  • Run unit tests
  • +
  • Run static analysis
  • +
  • Deploy
  • +
+

Identified the tools, POC'd each one, and evaluated which we wanted to tackle for consolidating to a single tool. GitHub Actions was a clear winner.

+ +

Why GitHub Actions?

+ +

Pros

+
    +
  • Everyone's code already lived in GitHub
  • +
  • Growing infrastructure and support for packages and workflows
  • +
  • Could use GitHub runners to run the code
  • +
  • Teams wouldn't need to leave GitHub
  • +
  • Secret management by repo
  • +
  • We were already paying for GitHub EMU, and Actions came included as part of it β€” made sense cost-wise in the long run
  • +
+ +

Challenges

+
    +
  • Immature enterprise feature set
  • +
  • Required custom reusable workflows
  • +
  • Runner infrastructure costs
  • +
  • API rate limits
  • +
  • Workflow architecture constraints
  • +
+ +
+ +
+
+
+

The First POC

+

I partnered on the first end-to-end CI/CD proof of concept, proving GitHub Actions could satisfy our enterprise software delivery requirements.

+

This included:

+
    +
  • Source checkout
  • +
  • npm environment provisioning
  • +
  • Dependency installation
  • +
  • Unit testing
  • +
  • Security scanning
  • +
  • Docker image creation
  • +
  • Artifact publishing
  • +
  • Enterprise deployment
  • +
+
+ +
+

What We Built

+

I then switched my focus to making and maintaining the reusable components across the stack and own the runner infrastructure.

+

Over the next few years, the proof of concept became the foundation of our internal CI/CD platform. This was a true team effort.

+
    +
  • Full Onboarding Documentation
  • +
  • ARC runners
  • +
  • Reusable workflows
  • +
  • Meta pipeline
  • +
  • Unit test uploads
  • +
  • Security scanning
  • +
  • Artifact management
  • +
  • Standardized change request creation
  • +
  • Attestation tracking
  • +
+ +

All of it funnels through one deployment platform at the end, to a managed Kubernetes infrastructure.

+ +

Language support rollout order

+
    +
  • 1. npm/JS
  • +
  • 2. Maven/Java
  • +
  • 3. Python
  • +
  • 4. Go
  • +
+
+
+
+ +
+ +

3,000+ engineers

+

300,000+ repositories

+
+ +
+ + +

What I'd Change

+

I would have built the reusable components before the meta pipeline, and limited the depth of reusable workflows so we didn't hit platform limits.

+

The meta pipeline was cool β€” once you're on it, you fly. Teams didn't need to maintain security findings in downstream packages or update external packages and dependencies in their workflows themselves; the platform (us) handled it.

+

But it's hard to onboard onto: users only get visibility into inputs at the top level, not into the depth of the whole pipeline underneath. Those inputs get mapped through a set of reusable workflows and actions we defined, and when you're dealing with actions and filesystems across runners, that's a real challenge β€” it made onboarding harder for teams.

+

I would have added comprehensive documentation sooner than we did.

+ +

Tradeoffs

+

Standardization vs. flexibility: enforcing a single opinionated pipeline improved maintainability and consistency at scale, but reduced teams' ability to handle edge cases. Over time, this also made the meta-pipeline harder to onboard onto.

+

For those scenarios, we encouraged teams to compose reusable components and run custom workflows in their own order rather than relying on the meta-pipeline.

+

However, that rigidity increased support load and onboarding friction, as teams needed more hands-on guidance to fit within the framework. It also consumed engineering time that could have gone toward building features or addressing system-level issues. We often found ourselves reasoning about edge cases from a constrained, "paved road" perspective, with limited ability to accommodate deviations without undermining the model itself. We bent where we had to, yet stayed firm the other times β€” it was a process.

+ +

Architecture...

+
+
+ + + + + diff --git a/work/enterprise-ai-adoption.html b/work/enterprise-ai-adoption.html new file mode 100644 index 0000000..7b21db3 --- /dev/null +++ b/work/enterprise-ai-adoption.html @@ -0,0 +1,292 @@ + + + + + + Enterprise AI Adoption β€” Austin Edmonson + + + + +
+
+
+ + + +
+
+ Austin Edmonson +
+ + +
+ +
+ ← +

Enterprise AI Adoption

+ +
+ +

...

+
+ +
+ +

...

+
+ +
+ +
    +
  • ...
  • +
+
+ +
+ +

...

+

...

+
+ +
+ +

What I'd change...

+

Tradeoffs...

+

Architecture...

+
+
+ + + + + diff --git a/work/github-actions-platform.html b/work/github-actions-platform.html new file mode 100644 index 0000000..db976a0 --- /dev/null +++ b/work/github-actions-platform.html @@ -0,0 +1,359 @@ + + + + + + GitHub Actions Platform β€” Austin Edmonson + + + + +
+
+
+ + + +
+
+ Austin Edmonson +
+ + +
+ +
+ ← +

GitHub Actions Runner Platform

+ + Blurred, motion-streaked photo of multiple runners mid-stride, evoking parallel execution and speed + +
+ +

GitHub-hosted runners were fast and convenient, but the compute cost didn't scale with our usage. We needed a self-hosted alternative.

+

As our Paved Road scaled to more users, those self-hosted runners started showing cracks:

+
    +
  • Long queue times
  • +
  • Infrastructure instability
  • +
  • Runners were too lightweight, leading to slow dependency and artifact downloads, which led to even longer queue times
  • +
  • Not enough runners, too many runners, not enough runners, too many runners
  • +
+

We were dependent on on-prem self-hosted machines, which gave us good compute per cost β€” but because of network issues and intermittent outages, we'd run out of runners entirely.

+

At that point, the very users we had successfully onboarded onto the Paved Road were now experiencing delays and outages β€” and the support channel noise let us know.

+

Those of us lucky enough to be on-call felt it usually at 2am EST.

+
+ +
+ +

This was a team effort. I focused on two core problems:

+
    +
  • Runner startup times were slow because every ephemeral runner had to redownload dependencies and artifacts.
  • +
  • Runner capacity constantly swung between overprovisioned (wasted compute) and underprovisioned (long queue times).
  • +
+

At the time, I was still relatively new to Kubernetes and Terraform, so I spent the first couple of weeks understanding how Actions Runner Controller worked internally, why the existing architecture behaved the way it did, and where the scaling bottlenecks actually were.

+
+ +
+ +
    +
  • Runner startup times were slow because every ephemeral runner had to redownload dependencies and artifacts.
  • +
+

The answer was hidden in the problem itself. Every runner started from a minimal base image, so each workflow spent time reinstalling the same tools before any application code could run.

+

I built a custom runner image on top of our base image that pre-installed the most commonly used tooling, closely mirroring GitHub-hosted runners without unnecessarily bloating the image. This shifted installation work from every job execution to the image build process, reducing startup time while preserving the flexibility of ephemeral runners.

+

I then updated our Helm charts so runner pods used the custom image alongside a Docker-in-Docker (DinD) sidecar, allowing every newly provisioned runner to start with the required tooling already available.

+ +
    +
  • Runner capacity constantly swung between overprovisioned (wasted compute) and underprovisioned (long queue times)
  • +
+

I led the migration from the original RunnerDeployment model to the newer RunnerScaleSet architecture in ARC v2. Although the newer model is conceptually simpler, it relies on an entirely different scaling mechanism, so the migration required redesigning how runners were provisioned.

+

Instead of relying on Kubernetes HPA to guess capacity, ARC began watching GitHub's job queue and provisioning ephemeral runners only when work existed. That allowed us to eliminate idle runners, scale all the way down to zero when inactive, and significantly reduce queue times while improving availability. But also scale all the way up at peak time should we need more runners.

+
+ +
+ +
    +
  • How did you migrate without interrupting thousands of developers?
  • +
  • How did you validate the new scaling behavior?
  • +
  • Did you have to redesign Helm charts?
  • +
  • Were there authentication changes?
  • +
  • Did you run both systems side-by-side?
  • +
  • What metrics told you the migration was successful?
  • +
+
+ +
+ +

...

+

...

+
+ +
+ +

What I'd change...

+

Tradeoffs...

+

Architecture...

+
+
+ + + + + diff --git a/work/partida.html b/work/partida.html deleted file mode 100644 index 9a53a87..0000000 --- a/work/partida.html +++ /dev/null @@ -1,403 +0,0 @@ - - - - - - Partida β€” Ausb - - - - - - - - - -
- - ← Work - -
-

Product Β· Design Β· Platform

-

Partida

-

Immigration tech built for families, not lawyers. Product, design, and platform engineering from zero.

-
- -
- -
-
-

Product Impact

-
    -
  • 15 families onboarded to beta
  • -
  • 2 attorney partners providing feedback
  • -
  • Document tracking across 19 case types
  • -
-
- -
-

Platform Engineering

-
    -
  • 12 deploys/week on Railway
  • -
  • FastAPI + SQLAlchemy async, PostgreSQL
  • -
  • Firebase Auth (compliance-first)
  • -
  • HTMX + Jinja2 for progressive enhancement
  • -
-
- -
-

AI-Augmented Development

-
    -
  • Claude for architecture design & code review
  • -
  • 40% faster feature iteration with AI-assisted testing
  • -
  • Real-time schema migration planning
  • -
-
- - -
- -
-

Tech Stack

-
-

Backend

-

FastAPI, SQLAlchemy

-
-
-

Database

-

PostgreSQL async

-
-
-

Frontend

-

HTMX, Jinja2

-
-
-

Auth

-

Firebase Auth

-
-
-

Hosting

-

Railway, PostgreSQL

-
-
-

Role

-

Solo founder, all layers

-
-
- -
-
- - - - diff --git a/writing/cicd-same-image.html b/writing/cicd-same-image.html index 37a2288..af3ddf0 100644 --- a/writing/cicd-same-image.html +++ b/writing/cicd-same-image.html @@ -3,584 +3,603 @@ - We Stopped Trusting Deployments Until We Fixed This β€” Ausb - - - + We Stopped Trusting Deployments Until We Fixed This β€” Austin Edmonson - - -
- - ← All posts + + - +
+ ←

We Stopped Trusting Deployments Until We Fixed This

- - -
+ -
- Terraform is Like a Dishwasher β†’ -
+ Painting of a city skyline at dusk with a translucent square overlay and a building glowing orange -
+
- + -Because at the end of the day, most engineers are not afraid of deployments. + -They're afraid of uncertainty. + - - - \ No newline at end of file + diff --git a/writing/htmx-production.html b/writing/htmx-production.html deleted file mode 100644 index d1a5a3a..0000000 --- a/writing/htmx-production.html +++ /dev/null @@ -1,356 +0,0 @@ - - - - - - HTMX in production β€” Ausb - - - - - - - - - -
- - ← All posts - - -

HTMX in production: what nobody tells you about going hypermedia-first

- - -
- -
- ← Why we built Partida -
- -
- - - - - - - - \ No newline at end of file diff --git a/writing/index.html b/writing/index.html index 73a5761..3e8a261 100644 --- a/writing/index.html +++ b/writing/index.html @@ -3,411 +3,522 @@ - Writing β€” Ausb - - - + Writing β€” Austin Edmonson - - -
-

Writing.

-

Product, design, and engineering β€” things I learned the hard way or found worth sharing.

-
- -
- -
- - -
Jun
2026
-
-
LLM Non-Determinism is Useful. Until You Mistake it for Engineering Truth.
-
The model explores. The engineer decides. And the engineer has to decide whether the decision itself was made on solid ground.
- Engineering -
-
- - -
May
2026
-
-
We Stopped Trusting Deployments Until We Fixed This
-
Nothing destroys trust in deployments faster than realizing staging and production were never actually running the same thing.
- Platform -
-
- - -
May
2026
-
-
Terraform is Like a Dishwasher: Great for Daily Loads, Overkill for a Single Cup
-
If you've heard the word "Terraform" thrown around in tech circles and nodded along pretending to know what it means, you're not alone.
- Platform -
-
- - -
May
2026
-
-
We Were Overengineering Ourselves Into Operational Exhaustion
-
What happens when a small team inherits infrastructure patterns built for a platform org three times its size.
- Platform -
-
- - -
Apr
2026
-
-
Why we built Partida: the gap no one was filling in immigration tech
-
Most immigration software is built for lawyers, not families. Here's what we found when we actually talked to both.
- Product + + + +
+

Writing

+

Notes on platform engineering, CI/CD, and the systems I've built or broken along the way.

+ +
-
+ - diff --git a/writing/llm-non-determinism.html b/writing/llm-non-determinism.html index 2c8b307..63d114a 100644 --- a/writing/llm-non-determinism.html +++ b/writing/llm-non-determinism.html @@ -3,349 +3,375 @@ - LLM Non-Determinism is Useful. Until You Mistake it for Engineering Truth. β€” Ausb - - - + LLMs and Non-Determinism in Engineering β€” Austin Edmonson - + + -
+
+ ← +

LLMs and Non-Determinism in Engineering

+ - ← Writing - - -

LLM Non-Determinism is Useful. Until You Mistake it for Engineering Truth.

- + Abstract illustration of wavy blue and white bands with node points and connecting curves, evoking a data or vector field
-

Us software engineers are trained β€” hard wired β€” to love repeatability. Same input. Same output. Same test results. Same build artifacts. Same deployment behavior. Generally this meant it was safe, it could be trusted, depended on β€” especially when deploying to customers in production. Predictability is the yellow brick road to our Oz. When something behaves differently twice, we call that a bug, open a ticket or a pull request, iterate, write tests, and patch it.

- -

Then LLMs showed up.

- -

You give the model the same prompt twice, and it may give you two different answers. Not wildly different, necessarily. Sometimes just different wording. Sometimes a more closely related example. Sometimes a small hallucinated goblin with a polite smile wearing a confidently worded hat. Sometimes, as we've seen more than we'd like, far worse. This notion can make any of us feel uncomfortable β€” unsure β€” because it challenges our paradigm of what software engineering is. For me though, as someone self-taught, my paradigm was always a little grey. You always needed some creativity within the documentation and Stack Overflow threads to make sense of what is truth, what is lies, and what are possible solutions.

- -

LLM non-determinism is useful for exploration, but dangerous when misunderstood in production engineering.

- -
- -

LLMs are useful because they wander. They remix. They offer a second path from the woods. Sometimes they hand you a better abstraction. Sometimes they hand you a puddle of mud disguised as genius and call it an architectural design. The variability is not automatically bad. In fact, it is often the point.

- -

Before LLMs, we learned from Stack Overflow, blogs, docs, conference talks, random websites, and that one coworker who somehow knew every obscure Linux command or JVM flag. We have always relied on outside inputs to stretch our thinking. LLMs have changed the speed, volume, and shape of those inputs. It's not bad β€” it's just our new reality.

- -

But I think there's something worth pausing on here. It's not just that the inputs arrive faster. It's that the surface of the input has changed. When you read a blog post or a Stack Overflow answer, you're reading something a human chose to say, for reasons you can interrogate. There's an author with a context, a bias, a specific problem they were solving. When an LLM generates an answer, you're reading a statistically smoothed surface drawn from a vast latent space of text. It has no intent. It has no context of its own. It has no skin in the game. The shape of the artifact is the same β€” words, code, explanation β€” but the provenance is entirely different. That doesn't make it useless. It makes it a different kind of input, and I think we're still collectively learning what that means.

- -

They can push the boundaries of what is possible in our minds. They can surface approaches we would not have reached on our own. They can be the Jarvis to our Iron Man. They can give us language for an idea that is still foggy in our head. They can help us see the edges of a problem sooner. But despite the pros, this does not remove the engineer from the loop. It makes the engineer more important.

- -

Our job is to synthesize. To know enough about the system, the constraints, the failure modes, the customer, the runtime, and the use case to decide whether the model's output is actually valuable. Because for production engineering, that same non-determinism is dangerous when misunderstood. An LLM suggestion is not a source of truth, nor at the moment should it be. It is not a passing test. It is not a design review. It is not a deployment plan. It is a candidate.

- -

Maybe a good candidate.

- -

Maybe a very confident puddle of mud.

+

Software engineers are used to things being repeatable. Same input, same output. That's how we know we can trust our tests, builds, and deployments. When something behaves differently twice in a row, we treat it as a bug and fix it.

-
- -

I ran into this recently while working on a Kubernetes deployment for a paved-road pipeline. The application was a tiny cron job β€” it made API calls, aggregated data, and wrote results to a BigQuery table in GCP. The ask was simple: adjust the deployment path so we could run a dry-run style deployment without executing the entire workflow.

- -

The LLM produced a clean-looking change. The Kubernetes YAML was valid. The surrounding code changes looked reasonable. The explanation was confident. Nothing immediately looked wrong.

- -

The problem was that it changed part of the parameterization in our overlay. Values that were expected to remain strings were transformed into literals. The deployment was now looking for something that didn't exist.

+

LLMs don't work that way. The same prompt can give you different answers. Sometimes the difference is small. Sometimes it's not. This can feel uncomfortable because it goes against what we're used to.

-

The model wasn't being malicious. It wasn't even obviously wrong. It was making what looked like a reasonable change based on patterns it had seen before.

+

But it's not automatically bad. That variability can be useful when you're exploring ideas or looking for new approaches. The problem is when you treat an LLM's output the same way you'd treat code you wrote yourself or reviewed carefully.

-

That's the danger. Most bad LLM outputs don't look ridiculous. They look correct enough to skip verification.

+

Before LLMs, we already learned from imperfect sources β€” documentation, forums, blogs, coworkers. LLMs are just another source, faster and broader. But there is a difference worth paying attention to: a human author has context, intent, and accountability. An LLM has none of that. It generates text based on patterns. It doesn't know what's true or what matters. That doesn't make it useless. It just means you have to treat it differently.


-

What's interesting is that the same model also helped me solve a different deployment problem that same week. It helped me rethink how we handled environment variables across our deployment workflows. Instead of relying on lifecycle-specific .env files and complex custom parsing logic, we simplified the flow by exposing configuration through the deployment at runtime and letting Kubernetes handle it as intended.

+

Example: I was working on a Kubernetes deployment for a small cron job that writes to BigQuery. I needed to add a dry-run option. The LLM gave me YAML and code changes that looked fine at first glance. But it changed how some parameters were handled β€” strings became literals β€” and the deployment broke because it was looking for values that no longer existed.

-

The result was a cleaner design that made it easier to support additional deployment paths without introducing more conditional logic or overengineering.

+

That same week, the same model helped me simplify how we handle environment variables across deployments. We removed some messy custom logic and let Kubernetes do more of the work. It worked well.

-

Same model. Same week.

- -

One output created a subtle bug. Another helped simplify a system.

+

Same tool. One fix, one new bug.


-

So let the LLM push the edges of your thinking where creativity helps. Let it expand the space of possible approaches, surface alternatives, and challenge assumptions you might not have questioned on your own.

- -

But once you move from exploration into execution, the rules change.

- -

At that point, the work has to come back through boring, yet beautiful, engineering discipline. And the discipline itself has to get sharper. Tests can pass and encode the wrong behavior. Types can be syntactically valid but semantically wrong. Explanations can sound right and describe something that doesn't exist. The linter can catch syntax. It can't catch the subtle semantic drift where the model quietly changed what "done" means.

+

The takeaway:

-

We have to verify the verification. Not just "does this work" but "does this work the way I think it works."

+
    +
  • Treat LLM output as a suggestion, not a final answer.
  • +
  • Syntax and formatting can be correct while the logic is wrong.
  • +
  • Tests and linters help, but they don't catch everything β€” especially when the change looks reasonable.
  • +
  • The engineer is still responsible for understanding what the code actually does and whether it fits the system.
  • +
-

That separation matters.

- -

The model is good at generating possibilities. It is not accountable for consequences.

- -

That responsibility stays with the engineer.

- -

The model explores. The engineer decides.

- -

And increasingly, the engineer also has to decide whether the decision itself was made on solid ground, or on a surface that just looked solid enough.

- -
- - +

Use LLMs to generate ideas and surface possibilities. But when you move from thinking to shipping, apply the same careful review you would to any other change. The LLM suggests. You decide. And you verify.

+
-
+ + diff --git a/writing/overengineering-operational-exhaustion.html b/writing/overengineering-operational-exhaustion.html index fc0dc27..ddd79e4 100644 --- a/writing/overengineering-operational-exhaustion.html +++ b/writing/overengineering-operational-exhaustion.html @@ -3,447 +3,482 @@ - We Were Overengineering Ourselves Into Operational Exhaustion β€” Ausb - - - + We Were Overengineering Ourselves Into Operational Exhaustion β€” Austin Edmonson - + + -
+
+ ← +

We Were Overengineering Ourselves Into Operational Exhaustion

+ - ← All posts + A circular hole cut through a grassy hill, opening onto a blue sky with clouds - -

We Were Overengineering Ourselves Into Operational Exhaustion

- +
-
+

Your team shouldn't be the emotional support group for your architecture.

-
- ← Terraform is Like a Dishwasher - Why we built Partida β†’ -
+

There's a very specific kind of fear that enters a small engineering team when someone says:

-
+

"Don't worry, Terraform manages it."

- - - +

Sometimes the best infrastructure decision is not adding another abstraction layer.

+ +

Sometimes it's removing three of them.

+ +
+ + + + - \ No newline at end of file + diff --git a/writing/partida-gap.html b/writing/partida-gap.html deleted file mode 100644 index 9184b34..0000000 --- a/writing/partida-gap.html +++ /dev/null @@ -1,353 +0,0 @@ - - - - - - Why we built Partida β€” Ausb - - - - - - - - - -
- - ← All posts - - -

Why we built Partida: the gap no one was filling in immigration tech

- - -
- -
- ← Overengineering & Operational Exhaustion - HTMX in production β†’ -
- -
- - - - - - - - \ No newline at end of file diff --git a/writing/partida-technical-breakdown.html b/writing/partida-technical-breakdown.html index 11a3ca3..3b73b03 100644 --- a/writing/partida-technical-breakdown.html +++ b/writing/partida-technical-breakdown.html @@ -3,266 +3,309 @@ - Building Partida: A Technical Breakdown β€” Ausb - - - + Building Partida: A Technical Breakdown β€” Austin Edmonson - + + -
- - ← Writing - - +
+ ←

Building Partida: A Technical Breakdown

- + + + Surreal collage of a chalk cliff face fitted with windows like an apartment building, overlooking the sea
@@ -452,36 +495,39 @@

Where It Stands

The stack isn't exotic. It was chosen by asking the right questions first, building the simplest thing that could prove the idea, and earning complexity when the problem actually demanded it. That's the whole lesson from the interview I failed.

+
-
+ + diff --git a/writing/terraform-dishwasher.html b/writing/terraform-dishwasher.html deleted file mode 100644 index 3186e6e..0000000 --- a/writing/terraform-dishwasher.html +++ /dev/null @@ -1,566 +0,0 @@ - - - - - - Terraform is Like a Dishwasher: Great for Daily Loads, Overkill for a Single Cup β€” Ausb - - - - - - - - - -
- - ← All posts - - -

Terraform is Like a Dishwasher: Great for Daily Loads, Overkill for a Single Cup

- - -
- -
- ← Same Image, Different Clusters - Our small team was getting burnt out β†’ -
- -
- - - - - - - - \ No newline at end of file