Skip to content

Software Engineering

Building software is the easy part. Building it with other people is the job. Notes from the trade.

Software Engineering is a Team Sport

To play a team sport, you must learn to be a teammate.

NOTE 📜 This is a post about Software Engineering. All views are my own and do not represent my employer. Please review my Disclosures.

A passage that shaped my perspective on software engineering:

The point we've been hammering away at is that, in the realm of programming, lone craftspeople are extremely rare—and even when they do exist, they don't perform superhuman achievements in a vacuum; their world-changing accomplishment is almost always the result of a spark of inspiration followed by a heroic team effort.

A great team makes brilliant use of its superstars, but the whole is always greater than the sum of its parts.

Let's put this idea into simpler words: software engineering is a team endeavor.

This concept directly contradicts the inner Genius Programmer fantasy so many of us hold, but it's not enough to be brilliant when you're alone in your hacker's lair. You're not going to change the world or delight millions of computer users by hiding and preparing your secret invention. You need to work with other people. Share your vision. Divide the labor. Learn from others. Create a brilliant team.

The quote is from Titus Winters, Tom Manshreck, and Hyrum Wright in Software Engineering at Google. I read it in 2023, three years into my career, deep in pandemic-era habits: locked in the hacker lair, isolated from my team, convinced I had to deliver something singular to change the world (or at least my org). The book was a mirror. I needed to work with other people. I needed to share a vision.

My priorities have inverted since. Technical excellence and impact used to top the list; today it's teamwork, leadership, and mentorship. Some specifics.

A Team Sport

Software engineering is a team sport. Every role on a sports team has an engineering counterpart:

  • Coach → Manager. Sets strategy, develops players, calls the plays.
  • Team Captain → Tech Lead. A player on the field who rallies and directs.
  • General Manager → Director. Builds the roster, makes trade-offs on talent and resources.

The org chart and the roster have the same point: nobody runs the play alone.

Old me: take a feature, disappear for two weeks, surface for code review with the work "done" and "perfect." A solo run on a team field. Predictably:

  • The coach had the play. Requirements I'd assumed wrong, surfaced too late to fix cheaply.
  • The captain was on the field. Design choices nobody validated, defended past the point of usefulness.
  • The GM saw the roster. Someone on the team quietly building a parallel version of the same thing.

All of it preventable. All of it caused by not asking for feedback while I still could.

A player who only trains alone doesn't get better. They just get really good at the wrong thing.

Running alone, no team in sight

My Playbook

Joining a new team, the metric used to be time-to-landed-code. I'd read code in detail the first week, often the first day, with the goal of submitting something useful within two weeks. I still ship early. The priority is now people: you can't pick the right thing to ship if you haven't asked anyone what matters.

Example: find a problem your manager doesn't enjoy giving attention to. Take it.

Why it works: trust gets built where someone else stops paying attention. You learn how the team operates by inheriting one of its uglier corners, and you don't need permission to start.

Then I learn the culture, both team and org. Canvas enough people and the picture sharpens: where this org came from, how decisions actually get made, where growth happens. None of it is in a doc. All of it determines whether your work lands.

Example: can you tell your org's history, prototype to present, to someone who doesn't work there?

Why it works: if you can narrate the story, you understand the why behind the codebase, the org chart, the calendar invites. If you can't, you're optimizing for what looks important instead of what is.

Last, I try to sell a vision. This step comes after, never before. By now I've built credibility, mapped the culture, and earned an opinion. Maybe there's a tool I built that solves a recurring frustration. Maybe there's a roadmap-shaped gap nobody has named yet. Either way, it has to read as the natural next thing, not an outsider's pitch.

Example: if you had a free quarter, what would you build, and would your peers nod when you said it out loud?

Why it works: a vision your team nods at is a vision they'll help you ship.

Leaving the Lair

Three years in, I read a book about software engineering as a team sport. Six years in, I feel like I'm finally getting it down.

The best work I've done has been a heroic team effort. I shared a vision. I divided the labor. I learned from others.

Software engineering is a team endeavor. And I spend every day trying to be a better teammate.

Token Anxiety

Approaching daily Pro limit · resets in 6h

NOTE 📜 This is a post about AI. All views are my own and do not represent my employer. Please review my Disclosures.
range anxiety /reɪndʒ æŋˈzaɪ.ə.ti/ noun The fear that an electric vehicle will run out of charge before reaching a destination or charging station.

There's a similar phenomenon in the AI community: token anxiety.

token anxiety /ˈtoʊ.kən æŋˈzaɪ.ə.ti/ noun The fear that an LLM will exhaust its context or its credits before arriving at a solution.

You know the moment. You're chipping away at a hard problem, on the best model available, on the highest effort setting. You're almost there, and then the banner drops: Approaching daily Pro limit · resets in 6h. Will you make it to the terminating token?

That's one flavor; here's another. You hear AI is the future, you don't want to fall behind, so you buy one of the big-lab plans. You polish a shelved project here, spin up a new project there. A month in, you've used 12% of your quota, and you can't decide whether to feel relieved or guilty.

Or here's a third. You work in tech, your employer encourages AI use, and your usage caps may as well be unlimited. You watch the cool projects your colleagues are shipping and want one of your own. You know AI fluency is a big part of performance now, so you start hunting for ways to spend all those tokens.

Three scenarios, two failure modes. An empty tank, and a full one; not having enough tokens, and having too many.

Empty Tank

When tokens are scarce, the symptoms are both predictable and compounding.

Gemini CLI showing Pro and Flash both at 100% used, hours until reset

Rationing. You start asking the model less than you'd otherwise ask. The cap forces a triage that the work doesn't actually need. Each prompt becomes a small negotiation with yourself before it ever reaches the model.

Attachment avoidance. The first thing you cut is context. You stop pasting the file and describe it in prose. You hint at the error instead of showing it. Each attachment costs tokens, so you give the model less to ground on, and it generalizes from less. The output drifts toward generic, and you don't always notice why.

Model degradation. When the output disappoints, you assume the model was overkill and step down. Pro to Flash, Flash to Flash-Lite. Each step is a small concession: this question doesn't really need the smart model. Sometimes you're right. The trick is that you stop noticing when you're wrong.

Premature compression. The same anxiety that pushed the downgrade pushes you to trim the conversation before it's full. You /compress early to stretch the session, or auto-compression catches you mid-flow. The plan, the failed attempt, the thread you were following: gone. You restart on a thinner version of the problem and the model takes a wrong turn it had already corrected once.

Session splitting. Eventually you skip compression and start over. Work that should live in one continuous thread gets chopped into three. You spend tokens re-explaining where you were, paid in setup instead of progress.

Provider hopping. When Gemini finally caps out, you bounce to ChatGPT. ChatGPT is congested, you bounce to Mistral. Each switch loses the context you'd just rebuilt. You're chasing free tokens and paying in continuity.

Meter watching. By now /stats is a tic. You glance at the percentage between every prompt and weight each question by what it might cost. That's the wrong frame. The question is whether the answer is worth having, not whether you can afford to ask.

Settling. When every prompt feels taxed, you stop iterating. You accept the first draft because you can't afford another round. You stop asking for refactors. You stop asking for alternatives. The output is okay. Okay becomes the ceiling.

Burn out. Living inside these constraints is exhausting in a quiet, attritional way. You're working with a model that should make things easier, and instead you're rationing your access to it. Eventually you decide it isn't worth the friction, and you reach for the tools you trusted before.

Full Tank

You'd think the cure was more tokens. It isn't.

Claude Code session usage at 12%, weekly at 7% — plenty of room left

When tokens are plentiful, every incentive points toward burning them. You think you're falling behind. AI is showing up in your performance review. The dollars you spent on a plan demand to be amortized. So you use, and use, and use.

Trivial offloading. You start asking the model things you would have done in two seconds yourself. Renaming a variable. Looking up a flag. Reformatting a paragraph. The model's latency is higher than yours, but the tokens are "free," so you keep doing it. The muscle for the small things atrophies.

Drift. The bigger work catches the same habit. You let contexts grow long with stale code, dead chats, and abandoned plans. You retry from scratch instead of iterating. You let the model wander without guidance, because it has plenty of room to figure it out. The output gets worse, not better, and you respond by spending more tokens on it.

Project sprawl. With a great number of tokens comes a great number of side-projects. You start three demos in a week. Two are vibes, one has a real idea, and none of them ship. By Friday there's a fourth. The repos outpace the finished work. I'm still figuring out how to keep the portfolio from turning into a graveyard.

Burn out. This is the one I want to be honest about, because it's the reason I'm writing this.

When you're paying for the tooling, you want your money's worth. $20, $100, $200 a month is real money. So you use AI every chance you get. In the checkout line? Check out the long-running operation on your phone. Reading before bed? Perfect time to kick one off. Just woke up? Perfect time to check on it. The financial cost is fixed; the effort cost feels free.

It isn't. You're babysitting agents, holding the architecture in your head, deciding what they should work on next. You never stop thinking about the work. The model gets to forget. You don't.

We're not AI agents; we're human. We need rest, whether we choose it or not. The pause is where the work consolidates, where the bad ideas drop out and the good ones surface, where you remember what you were trying to build in the first place. None of that happens while you're checking on a build from the grocery store.

My current practice is to downgrade my plan once every few months for a month at a time. The lower cap forces me into intentional use, and the spare hours go into the things that aren't coding. It's the only thing that's worked; I'm curious if you've found others.

The Middle Lane

Range anxiety in EVs didn't get solved by 1,000-mile batteries. It got solved by chargers along the route, by trip planning, by drivers learning their cars. The fear faded as the fit got better.

OpenAI Codex showing 5h limit at 51% left, weekly at 61% left — the middle of the tank

Token anxiety won't be solved by infinite limits either. The cure isn't a bigger battery; it's knowing the route. Decide what the work is worth before you ask. Spend where the answer earns it. Hand some of the small tasks back to yourself, so the big ones get the version of you that actually shows up.

A low tank exhausts you quickly. A full tank exhausts you slowly. Only the middle is sustainable.

On Being Passionate About Tools

Get to work. Grab a cup of coffee, some water. Possibly breakfast.

Sit down at my desk. Log into my computer, look at i3wm.

Launch a new terminal session. ranger. Enter. Navigate to project. nvim. Enter.

space f. Use fzf to open necessary file.

This is a daily workflow for me. Before I start typing code, I use about four tools to get to it. Notice, I haven’t mentioned touching the mouse once yet; Because I haven't touched the mouse yet.

Throughout my academic and professional career as a software engineer, I spent a lot of time using tools. Trying new tools. Searching for tools. Customizing tools[1].

Although this might be a commendable feat, it is often met with skepticism. A lot of skepticism.

I've had at least a hundred conversations with people about tools, about why they advocate against using such tools. These conversations were with other students, senior software engineers, and tenured professors—and generally, almost all of them fell into three distinct buckets of people.

It’s a waste of time.

This is by far the worst yet best counterargument against investing so heavily into tools—and the reasoning is in the trailing three words.

waste. Better tools will objectively help one write more code. If there is a modification that needs to be made at the end of the file, it takes one keystroke to jump to that position in Vim. Picture doing this, but 100s of times a day.

of time. There is a time commitment, a big one. And there is a learning curve, and it is steep. So, one would have to justify the reasons for learning it. And I've done so below.

What I have works just fine.

I’m deeply skeptical of the “If it’s not broken, don’t fix it” mentality. There’s always room for improvement, and there’s nothing more I love to see than improvement.

It’s why we buy new phones. It’s why we like nice, new cars. It’s why we, as civilization, love progress.

Even if it’s a marginal increase, say 5% more code a week. With a 100 lines of code written a week, that can be a about 250 additional lines of code written a year. A marginal increase, sure; but a welcomed one.

It doesn’t really make you a better programmer.

I generally have three core reasons against this, and they are as follows.

It'll help write more code, faster. It is objectively faster to type more code if your hands never leave the keyboard. It's faster to navigate a filesystem without having to focus on where a cursor is. It's ridiculously faster to open a file by just typing out parts of the filename as opposed to navigating to it.

It's healthier. Legitimately. Minimizing hand travel will significantly put less strain on your hands, wrists, and arms.

It'll make you a better programmer. As programmers, we have to learn things all the time. New programming languages, new paradigms, new company software. Learning a new tool keeps a mind sharp by reinforcing how to learn something. Plus, the skills are fluid. Learning to navigate in Vim will help navigate in ranger. Learning regular expressions can be used in fuzzy searches. The skills are transferable.

So, where might one start? Again, there are three areas I see that can have the most benefit from improving your workflow.

Your operating system. Whether it’s Windows, MacOS, or Linux, you have to use an operating system. Get good at it. Learn the paradigms of the system. Learn how the file explorer works in Windows. Learn advanced features in MacOS like a spotlight alternative or simple hot corners. Or learn how to set up your WiFi drivers in Linux.

Your text editor. Choose ones that are portable. I use NeoVim. Many people have success with Emacs. Some people prefer a visual editor like Sublime Text or Atom. Learn their workflows. Learn the shortcuts of Emacs. Learn how to edit text in Normal Mode using Vim. Install packages in Sublime or Atom. You spend most of your time here anyway, might as well get familiar with it.

The intermediary layer between your operating system and your text editor. By this, I usually mean the shell, like Bash or ZSH. Learn how to grep or navigate around. Install packages to make tasks easier. It’s well worth it.

So, yes, I am a strong advocate of using advanced tools. Established tools. Great tools. And I hope I’ve convinced you to do the same.


  1. 145 commits worth. ↩︎