← Back to Blog

Summer 2026: From Building Apps to Understanding Systems

I started this summer thinking about whether code worked. I ended it thinking about how it fails, how it's deployed, how it's observed, how state moves between services, how data is validated, how systems recover, and how experiments stay reproducible. That's not a slogan I picked for a portfolio; it's the honest shape of what changed between May and August 2026, across an internship and four independent projects I kept building on the side.

The internship: pipelines that can say no

The DevSecOps internship was where the shift started, mostly because it put me in a position where my mistakes had a blast radius bigger than my own laptop. Working across Jenkins and GitLab CI/CD pipelines for services in four different languages, with security gates that could actually fail a build, taught me that a pipeline isn't a formality; it's the mechanism by which a team enforces what it refuses to ship. I wrote more about the specifics in the internship post, but the summary is: I stopped thinking of CI as a checkbox and started thinking of it as a policy engine.

MatchSense: failure is the default case, not the edge case

Building an event-driven system from scratch reframed how I think about correctness. In a request/response world, a bug is something you notice because a response is wrong. In an event-driven system, a bug can be a message that arrives twice and nobody notices until a stat quietly drifts. MatchSense forced me to design for at-least-once delivery as the normal case, not a defensive afterthought: idempotency, dead-letter handling, and distributed tracing stopped being buzzwords and became the only way I could actually debug what happened to one event across five services.

Market Pulse: idempotency, again, from a different angle

It's not a coincidence that Market Pulse taught me the same lesson from the data side. Ingestion jobs get re-run. Backfills overlap with incremental loads. If your write pattern isn't idempotent, "just re-run the pipeline" silently corrupts your tables instead of fixing them. The bigger realization was about verification: a fixture-based test proves your code is internally consistent, not that the real system behaves the way you assumed. I'd rather ship a documented benchmark methodology than a single favorable number I can't reproduce, and that's a standard I didn't hold myself to before this summer.

The Linux Kernel Lab: the error message lies about where the bug is

Nothing humbled me quite like building a kernel from source. Every real failure (a boot decompressor error, a module that wouldn't load, a panic in PID 1) looked like a different category of bug than it actually was. A compiler default changed a C standard. A toolchain mismatch between GCC and Clang/LTO broke module loading. An emulator's conservative CPU model produced an illegal-instruction panic that read like a kernel bug. The lesson generalizes past kernels: the layer that reports a failure is rarely the layer that caused it, and figuring out which layer actually owns the bug is most of the work.

MLOps and applied AI: the parts that don't show up in a demo

The Personal Cognitive Load Monitor and Company Research work rounded out the summer from a different direction: not "does the model work" but "what does it take to operate a model, or a retrieval pipeline, as a system." Drift monitoring, scale-to-zero serving, streaming partial results instead of blocking on a full response: none of that is visible in a notebook, and all of it is what separates a trained model from something you could actually run.

The through-line

Every one of these projects taught a version of the same lesson from a different direction:

  • How it fails: at-least-once delivery, retried ingestion, a boot panic that isn't what it looks like.
  • How it's deployed: GitOps and admission policies that hold regardless of what the pipeline intended.
  • How it's observed: a trace across five services instead of five sets of logs and a guess.
  • How state moves: Kafka as the durable log, Redis as the current-state cache, and knowing which one owns which fact.
  • How data is validated: tests that state invariants about data, not just about code paths.
  • How systems recover: Blue-Green cutovers, dead-letter queues, self-healing GitOps.
  • How experiments are reproduced: a benchmark methodology instead of a single number, a fixture instead of a live call, a script instead of a screenshot.

What's next

I'm not done with any of these. MatchSense and Market Pulse are both still active, the Linux Kernel Lab left me wanting to go further into driver work, and the internship changed what I look for in a team's engineering culture before I'd want to join it. If a common thread runs through all of it, it's that I stopped being satisfied with "it works on my machine" a long time ago, and this summer is where I finally built enough things that failed in enough different ways to actually believe that.