Welcome to my world!

Welcome to my world!

I'm a software engineer who cares deeply about clarity, usability, and getting the details right.

I'm a software engineer who cares deeply about clarity, usability, and getting the details right.

Brand Logo
Icon
1

<!--

Work info

-->

Company:

VAE, Inc.

Role:

Software Engineer

Year:

2026

Work Image

Project Overview

This project focuses on incrementally converting a legacy ASP.NET codebase from traditional controller-based APIs to ASP.NET Minimal APIs. The goal is to modernize the API surface while improving clarity, reducing boilerplate, and aligning the codebase with more explicit, composable patterns.

This work is still in progress. Rather than a wholesale rewrite, the conversion is being approached deliberately and incrementally, balancing modernization with stability in a production system.

Background & Motivation

While working in the existing codebase, I began to notice recurring friction points in the controller-based approach:

  • Controllers had grown large and difficult to reason about

  • Routing, authorization, binding, and business logic were often intertwined

  • Simple endpoints required significant ceremony

  • Cross-cutting concerns were handled inconsistently across controllers

Although controllers are a familiar and powerful abstraction, many endpoints no longer benefited from the structure they imposed. In several cases, the abstraction obscured intent rather than clarifying it.

Minimal APIs offered an opportunity to:

  • make endpoint behavior explicit at the point of definition

  • reduce indirection between routing and execution

  • compose concerns more intentionally

  • modernize without introducing a new framework

Problem Statement

The core problem was not that controllers were “wrong,” but that their cost had begun to outweigh their benefit for many endpoints.

Specifically:

  • Endpoint behavior was spread across attributes, base classes, and filters

  • Understanding an endpoint often required jumping between files

  • Boilerplate obscured the actual logic being executed

  • Adding new endpoints required copying patterns without always understanding them

As the system evolved, this made the API layer harder to change confidently.

Approach & Constraints

Several constraints shaped how this conversion could begin:

  • The codebase is production-critical and cannot be rewritten wholesale

  • Existing routing and authorization behavior must be preserved

  • Minimal APIs must integrate cleanly with existing middleware

  • Dependency injection and logging must remain explicit and predictable

  • The conversion must coexist with controller-based endpoints during transition

Given these constraints, the approach was to introduce Minimal APIs selectively, using them where they provided immediate clarity without destabilizing the system.

Early Decisions
Favor incremental adoption over full migration

Rather than attempting a large-scale rewrite, I started by identifying endpoints that:

  • were simple and self-contained

  • had minimal shared state

  • suffered most from controller overhead

These endpoints were good candidates for early conversion and learning.

Make behavior explicit at the endpoint boundary

Minimal APIs place routing, binding, authorization, and execution logic in one place. I leaned into this by:

  • defining dependencies explicitly in method signatures

  • making authorization requirements visible at the endpoint level

  • keeping endpoint logic small and focused

This helped make each endpoint understandable in isolation.

Preserve existing behavior before improving structure

Early conversions prioritized behavioral parity over refactoring. The goal was to:

  • match existing request/response shapes

  • preserve status codes and error handling

  • avoid introducing breaking changes

Structural improvements can follow once confidence is established.

Early Implementation Work

Initial work involved:

  • defining Minimal API endpoints alongside existing controllers

  • wiring routing and authorization to match legacy behavior

  • validating request binding and cancellation token behavior

  • ensuring logging and dependency injection behaved consistently

This phase surfaced subtle differences in how Minimal APIs handle:

  • model binding

  • cancellation token propagation

  • filter and middleware interaction

Each difference required careful validation rather than assumption.

Open Questions & Active Exploration

Because this work is ongoing, several questions are still being evaluated:

  • When does controller structure still provide meaningful value?

  • How should shared logic be factored without recreating controller-like abstractions?

  • What patterns scale cleanly as the number of Minimal APIs grows?

  • How should testing strategy evolve for endpoint-centric definitions?

These questions are shaping how the conversion proceeds and where Minimal APIs are appropriate.

Tradeoffs & Risks
Early tradeoffs include:
  • Reduced familiarity for engineers used to controllers

  • Risk of inconsistent patterns during transition

  • Additional upfront thought required to structure endpoints well

These risks are being managed by:

  • limiting initial scope

  • documenting emerging patterns

  • favoring clarity over cleverness

Current Status

At this stage:

  • Minimal APIs have been introduced selectively

  • Early endpoints are live and behaving as expected

  • Patterns are beginning to emerge, but are not yet locked in

  • Further refactoring and standardization are planned

This case study will evolve as the work matures.

Reflections (So Far)

Even early in the process, a few insights are already clear:

  • Minimal APIs reward intentional design

  • Reduced abstraction increases both power and responsibility

  • Explicitness improves confidence when changing code

  • Modernization works best when it’s incremental

What I’m Intentionally Not Doing (Yet)

I am intentionally not:

  • forcing all endpoints into Minimal APIs

  • abstracting prematurely to “standardize” patterns

  • removing controllers that still serve a clear purpose

Restraint at this stage is critical to avoid trading one form of complexity for another.

Results

0

Improvement in feature engagement

0

Customer support interactions

0

App Store rating

Building and evolving production systems under real-world constraints

Social Icon
Social Icon

Building and evolving production systems under real-world constraints

Social Icon
Social Icon

Building and evolving production systems under real-world constraints

Social Icon
Social Icon