Professional

Zach Larson

Senior .NET developer, full-time since August 2016.

Record · The Bancorp · June 2018 to September 2026

  1. The organisation's Angular application template November 2018 to June 2026 · sole author
  2. The enterprise transactional email platform December 2018 to August 2026 · principal author
  3. The admin tool over internal program settings and their audit history September 2023 to May 2026 · sole author
  4. The general-ledger upload system for deposit accounting January 2024 to July 2026 · sole author
  5. The bulk source-repository mirroring utility April 2024 to May 2026 · sole author
  6. The account services desk for bank operations staff December 2024 to June 2026 · principal author
  7. The internal real-time messaging bus July 2025 to June 2026 · sole author
  8. The log-reading tool, still a scaffold November 2025 to June 2026 · principal author

32 systems · 9 started from an empty folder · 5 sole author · the full record →

Recurring decisions

The general-ledger upload system for deposit accounting

Purpose

Builds, checks and posts the general-ledger entries that deposit accounting depends on, from templates and batches through to real-time posts. Three legacy console applications feed it.
Originstarted from an empty folder
Commit share99% · sole author
SpanJanuary 2024 to July 2026

as of 2026-09-06

The bulk source-repository mirroring utility

Purpose

A small utility that clones the whole organisation's source repositories in one pass. Built to the same standard as the applications, with its own test project.
Originstarted from an empty folder
Commit share96% · sole author
SpanApril 2024 to May 2026

as of 2026-09-06

The organisation's Angular application template

Purpose

The project template most of the bank's Angular web applications were copied from, with authentication, environment routing and the wrapper-API pattern already wired.
Originorigin unknown
Commit share94% · sole author
SpanNovember 2018 to June 2026

as of 2026-09-06

The internal real-time messaging bus

Purpose

Infrastructure rather than an application. One system publishes a notification, another subscribes to it, and the two never have to know about each other.
Originstarted from an empty folder
Commit share93% · sole author
SpanJuly 2025 to June 2026

as of 2026-09-06

The admin tool over internal program settings and their audit history

Purpose

Read and edit the configuration values other internal systems run on, with a full audit history of every change, across three separate databases.
Originstarted from an empty folder
Commit share93% · sole author
SpanSeptember 2023 to May 2026

as of 2026-09-06

The account services desk for bank operations staff

Purpose

What operations staff use to look up a customer or an account, change an address, handle returned mail, update a customer email, and trigger a user id or password reset. A nightly job clears the returned-mail queue behind it.
Originstarted from an empty folder
Commit share84% · principal author
SpanDecember 2024 to June 2026

as of 2026-09-06

The log-reading tool, still a scaffold

Purpose

A repository created, set up, and documented as having no source in it yet. An honest placeholder rather than an abandoned half-application.
Originstarted from an empty folder
Commit share83% · principal author
SpanNovember 2025 to June 2026

as of 2026-09-06

The enterprise transactional email platform

Purpose

The queue every internal system hands its customer email to. Persists the message and its attachments, ships a typed client library and a shared models package, and a downstream worker sends. The largest single body of work in the estate by volume.
Originjoined an existing codebase
Commit share80% · principal author
SpanDecember 2018 to August 2026

as of 2026-09-06

Endpoints over controllers

Statement

Every HTTP endpoint is its own class carrying its own request and response types, rather than a controller holding a dozen loosely related actions.

Rationale — in his words

Controllers bloat. Finding one action means scanning hundreds of lines or hunting for a method, on top of the decorators a standard controller carries. FastEndpoints does not merely permit one endpoint per file, it expects it, and it keeps that file minimal. The hard work belongs in the service.

Trade-off

More files. A five-operation feature is five endpoint classes plus its contracts, where a controller would have been one file.

Evidence

  • The general-ledger upload system for deposit accounting
  • The admin tool over internal program settings and their audit history
  • The account services desk for bank operations staff

Never throw out of a service

Statement

Every service returns a result envelope. Failure is a value the caller has to handle, and only the endpoint layer turns that value into an HTTP error response. The rule is written down inside the repositories that follow it.

Rationale — in his words

Exception flow never feels like it carries enough substance. Did it really fail, or was the exception planned? Did it come from the direct parent or bubble up from further down? Attaching a message to it is not an option. A result envelope behaves the way he wants code to behave and leaves far more room to move.

Trade-off

Every call site has to unwrap. Where a failure genuinely is exceptional, a result envelope is more ceremony than a throw would have been.

Evidence

  • The account services desk for bank operations staff
  • The enterprise transactional email platform

The browser never touches the API

Statement

A server-side hop sits between the browser and the API. The browser talks to that hop, the hop attaches the caller's identity and forwards. In one system the browser cannot reach the API at all.

Rationale — in his words

A security environment requirement, not a preference. Individual users are not to reach an API at all, and that needed a hard cut: only service accounts may call one. The hop in front is what guarantees no human ever gets there directly.

Trade-off

An extra deployable, an extra hop of latency, and every endpoint exists twice: once on the API and once as the pass-through in front of it.

Evidence

  • The admin tool over internal program settings and their audit history
  • The general-ledger upload system for deposit accounting
  • The account services desk for bank operations staff

Authorization decomposed to the action

Statement

Permissions are granted per action, not per record. Approving, back-dating, auto-reversing, voiding, changing a settlement date and editing the field that grants access are each their own permission, separate from ordinary edit.

Rationale — in his words

The standard set is read, edit and admin. Anything past those came either from planning the application up front or from discovering over time that a finer permission was needed. Both routes produced entries in the list.

Trade-off

More roles to administer, and a permission model somebody has to keep a map of.

Evidence

  • The general-ledger upload system for deposit accounting
  • The overnight sweep, overdraft and settlement processor
  • The internal IT ticketing and asset register

Legacy marked, not deleted

Statement

A repository that is superseded but still standing gets a LEGACY prefix on its name. The prefix stops anyone making changes to it, and it stays until the repository is confirmed safe to remove from master. Renaming a project is easier to reason about than hunting for the commit to revert to, so the old thing is kept, labelled, as the rollback path.

Rationale — in his words

The prefix exists to stop other people editing a repository that is superseded but still standing. It stays until that repository is confirmed safe to remove from master, because renaming a project is easier to reason about than hunting for the commit to revert to.

Trade-off

Dead repositories stay in the estate, visibly, and somebody has to decide when each one is finally safe to remove.

Evidence

  • The enterprise transactional email platform

Shared contracts, so legacy consumers move on their own schedule

Statement

A contract package targets both the modern runtime and the decade-old one, so callers on either share the same types. Where that is not possible the old and the new ship side by side as two packages rather than as one breaking upgrade.

Rationale — in his words

It was a bear. Wrappers and converters carry the old request models alongside the new ones that gained functionality, and unit testing was what made it survivable, probably more than on any other project he has worked on.

Trade-off

Two runtimes to keep a package building against, and a lowest common denominator on anything the old target cannot express.

Evidence

  • The internal real-time messaging bus
  • The payment solutions support platform
  • The shared internal package estate

Record the correction; label an inference as an inference

Statement

A superseded decision is struck through and dated rather than overwritten, and where an implementer reasoned but nobody actually ruled, the entry is labelled an inference pending a decision, with the reasoning chain and the alternative reading both stated. In one estate the written record is checked mechanically against the code: retired terms surviving unmarked, citations of decisions that do not exist, verification claims whose covered files have moved.

Trade-off

The record gets longer and messier to read, and somebody has to keep the checks working.

Evidence

  • The ACH and government payment processing suite