The Feature Became an Afterthought

The Feature Became an Afterthought

For the WPBL season, we built a live baseball stats system that updates the website while the game is happening.

It shows the score, the inning, who is at bat, who is on base, pitch velocity, exit velocity, hits, runs, box scores, and player stats. Fans can watch the game and see the site change without refreshing the page.

At peak traffic on opening day, the site was approaching a million page views. The live service had to hold open connections for tens of thousands of people at once.

A few years ago, that would have sounded like a project to postpone, buy from a vendor, or put in front of a dedicated engineering team.

This time, it became a small Go service on a tiny EC2 instance.

That does not mean it was trivial. It means something important has changed about which ideas are worth attempting.

The job was more than putting scores on a page

The league already had two separate systems doing real work during games.

One system handled scorekeeping and baseball statistics. The scorekeeper entered the live game state: the score, runs, hits, who was batting, who was on base, and the rest of the box score.

Another system was connected to the radar equipment measuring pitches and batted balls. That gave us data such as pitch speed and exit velocity.

Both services had independent APIs. Neither one was designed to become the complete live-data layer for the website.

The actual project was to stitch them together.

That meant matching players across systems, reconciling game state, combining event feeds, calculating and aggregating stats, and turning the result into a clean internal data model that could be used in several places on the WordPress site.

Then there was the live delivery problem. The site could not make people refresh a box score every thirty seconds. It needed a persistent connection that could send changes as they happened, while safely handling a large number of concurrent viewers.

This was not one feature. It was a data-integration project, a stats engine, a high-concurrency service, a WordPress plugin, a frontend application, and an operations problem.

Baseball has more edge cases than you remember

The hard part was not just receiving data from two APIs.

Baseball has a deep vocabulary of statistics, and every one can be sliced a few different ways. A fan might want a player’s stats for the current game. A coach might want a season total. A page might need team stats, league leaders, or a box score that updates after every event.

How do you calculate RBIs by game, season, player, or team? How should an earned run be handled? Which events affect the current game state? What happens when a player’s name is represented slightly differently in two systems?

Normally, working through that catalog would mean weeks of research, implementation, and testing. Instead, the AI could help explore the rules, inspect the incoming data, write aggregation code, identify missing cases, and revise the implementation as the real shape of the data became clearer.

The result was a system that understands more baseball statistics than I do. That is not a claim that the AI made the decisions alone. The system still needed someone to define what it was supposed to do, inspect results, and recognize when something looked wrong.

But the distance between “we should have this capability” and “we have a useful first version” got dramatically shorter.

Choosing Go without being a Go developer

My strongest backend background is Python. I started there and got a working version of the service running.

But the traffic profile made the language choice worth thinking about. This service needed to stay on all the time, keep a large number of WebSocket connections open, and use very little memory on an inexpensive server.

The options that made sense from the beginning were Rust or Go. Both are better fits for a service with a lot of concurrent network activity than the kind of Python backend I would normally reach for.

I chose Go. I had tried to learn it a couple of times and found it frustrating. I was not going to hand-write a mature Go service from memory.

That was exactly the point.

I could explain the architectural requirements: WebSockets, connection lifecycle, shared state, memory pressure, reconnection behavior, and a service that could survive a big opening day without requiring a large machine. The AI could take a working Python version and help rewrite it in Go in about twenty minutes.

The rewrite was not the whole project. It still had to be tested and operated. But it turned a language barrier into an implementation detail.

This is consistent with what I found while building a production SaaS with AI: the model is exceptionally good at removing implementation drag once the target is clear. The human job moves toward deciding what good looks like, which tradeoffs matter, and what needs to be checked.

Opening day was the test we could not simulate

There was no way to fully rehearse this before a real game.

Weather and scheduling meant we could not get a live game’s worth of scorekeeping events, radar events, traffic, and long-lived WebSocket connections all at once. We tested what we could. But opening day was still the first real proof.

It mostly worked.

Halfway through the game, a small memory leak surfaced and the server became overloaded. I rebooted the instance. The service came back. After that, we used the same AI-assisted workflow to inspect memory behavior, identify likely connection-cleanup issues, and reduce memory use.

There were also a few data-parsing cases that only appeared during a full game. Those got fixed after seeing real events move through the system.

That is not a story about perfect software. It is a story about a manageable failure mode.

The system did not need a massive war room or a long vendor escalation path. We could connect to the instance, inspect the process, formulate a hypothesis, make a change, and deploy it. The confidence came partly from knowing there was a fast path to a fix if reality exposed something the test environment had missed.

Today the service runs with remarkably low memory usage on a very small server.

This is one reason AI-operable systems matter. AI is much more useful in production when the system exposes logs, metrics, commands, and clear ways to inspect and change its state. The coding agent is not a substitute for observability. It becomes more valuable when observability is there.

The backend was only half the product

The live service feeds a WordPress plugin that provides custom blocks and widgets for the WPBL site.

The plugin includes frontend JavaScript that opens and manages the WebSocket connection, receives updates, and changes the page in real time. It also includes the theme work: CSS and components designed to look like the rest of the site rather than a separate stats product bolted onto it.

That is the part I keep coming back to. The work crossed a surprising number of boundaries:

  • External scorekeeping and radar APIs
  • A data-matching and stats-aggregation layer
  • A concurrent Go microservice
  • WebSocket connection management
  • Operational tools for auditing and debugging live data
  • A WordPress plugin with custom blocks and widgets
  • Browser code, theming, and live visualizations

One small service now pulls data in, combines it, keeps player identities straight, publishes live updates across the site, and supports post-game updates without unnecessary data entry.

The league owns that layer. It is not just a screen from somebody else’s product embedded on the site.

The lesson is not that software is free

It would be easy to tell the wrong version of this story.

AI did not make architecture irrelevant. It did not eliminate production failures. It did not make it safe to ship without watching the system. The opening-day memory leak is a good reminder that software still meets reality.

And it did not tell us which project was worth building. That judgment still comes first.

What changed is the cost of implementation and iteration.

There are features that used to feel like custom-software territory: live data feeds, data integration, high-concurrency backends, custom WordPress components, and sport-specific visualization. A small organization would often treat those as out of budget before it had even explored the idea.

Now, if someone on the team can articulate the system, recognize the relevant technical constraints, and validate the output, the first version may be only an hour of focused prompting and iteration away.

That does not make the result disposable. It makes ambition cheaper.

Features are becoming an afterthought

The most striking part of this project is that most people around it do not fully appreciate how much infrastructure sits underneath the feature.

They asked for live scores, box scores, and a visual view of the current situation in the game. Now those things exist on the site. From the outside, they just look like reasonable things for a modern league website to have.

That normality is the signal.

When a formerly ambitious capability becomes easy enough to implement, the organization stops debating whether it is possible. The feature becomes an expectation. It becomes background.

That is where the opportunity is for technical people and operators right now. Look for the things your organization has quietly accepted as too complicated, too custom, or too expensive. Some of those assumptions were formed when implementation was the bottleneck.

It is not always the bottleneck anymore.

The useful question is no longer just, “Can AI write this code?”

It is, “What would we build if the hard part of implementation got much cheaper?”

For the WPBL, the answer was a real-time baseball data system that runs on a tiny server and makes the website feel more alive during a game.

For other organizations, the answer will be different. But more of those answers are now within reach.

What I built with AI this week

Real projects, real results. One email every Tuesday.


About

Co-founder of Psychedelic Water. 20+ years building software, shipping products, and using AI to do both faster.

View Portfolio


Follow along

X / Twitter

YouTube

Instagram