Most applications can afford to treat time as a familiar thing: a date, a timestamp, maybe a timezone conversion. In a system responsible for scheduling and dispatching commands to satellites, time has a very different meaning.
My responsibility was the portion of that system that converted between UTC—the time JavaScript applications typically work with—and the TAI/J2000 representation used by the scheduling platform. Commands had to be validated, queued, and executed at precisely the intended moment and even small discrepancies could have downstream consequences. The scheduling system needed to translate reliably between the time standards used by people, software, and the underlying mission systems.
The Dangerous Kind of Bug
While implementing the conversion logic, I began noticing subtle inconsistencies in command execution times. They were small enough that they could easily have been dismissed as rounding or formatting differences. But in a system where timing matters, and “almost right” just isn’t right.
I traced the discrepancies through the scheduling pipeline and eventually found that the problem wasn’t in the feature I was building. It was in a foundational assumption the system had inherited.
UTC incorporates leap seconds. Because Earth’s rotation isn’t perfectly constant, UTC can drift relative to astronomical time. TAI does not. Instead leap seconds are added when the new second(s) are formally announced by the International Earth Rotation and Reference Systems Service (IERS). Since no leap seconds have been added since 2017 this issue had not yet surfaced. The relationship between them therefore depends on the point in time being converted and J2000 introduces another consideration that calculations need to be made relative to the correct reference epoch of which it was not.
A conversion that appears correct today can produce the wrong result for another date if those details aren’t accounted for and in precision-sensitive software, a wrong answer that looks right can be more dangerous than a loud failure.
Rebuilding Time From First Principles
Rather than adding another adjustment around the existing implementation, I stepped back and rebuilt the conversion pipeline around the actual astronomical time standards. I worked through the relationships between UTC, TAI, and J2000, including leap-second handling and the appropriate J2000 epoch. The implementation was then rewritten with explicit invariants rather than relying on a static offset.
The goal wasn’t merely to make the current test case pass. I wanted the conversion itself to express the rules it depended upon, so I added validation around edge cases and long-range dates, along with tests designed to catch discrepancies that might otherwise remain invisible until a scheduled command was already in the system.
Just as importantly, I isolated the conversion logic from the rest of the application. Time calculations are notoriously easy to get subtly wrong, and scattering them throughout scheduling code would make future verification much harder.
Making It Testable Without a Satellite
Correct conversion was only part of the problem.
The team also needed a safe way to verify the scheduling workflow without depending on access to a live satellite system.
I helped build a flat satellite model—a controlled representation of the system that allowed operators and engineers to submit mock commands, exercise scheduling behavior, and observe the resulting state transitions without interacting with live hardware.
That gave us a way to test more than isolated conversion functions. We could validate how timing behaved as part of the actual command workflow. It also helped expose edge cases earlier. Instead of discovering a scheduling problem after integrating with a live system, we could reproduce scenarios locally, inspect the resulting behavior, make corrections, and run them again.
For mission-critical software, that separation matters. Testing should make it easier to be aggressive about finding failures without making the consequences of those failures dangerous.
Deterministic Scheduling
The same philosophy extended beyond time conversion.
Commands moving through the scheduling system needed predictable behavior around validation, authorization, queueing, execution, and state. Given the same inputs and system state, the scheduler needed to reach the same conclusion every time.
I added safeguards around command execution and helped refine critical portions of that workflow so invalid or inconsistent states could be identified before commands progressed farther through the system. And the result was a more deterministic scheduling layer and a much clearer boundary between valid commands and conditions the system should reject.
That matters in any distributed application. It matters considerably more when the software eventually interfaces with a physical system that can’t simply be refreshed in a browser.
Correctness Over Convenience
By fixing the conversion at its source, we avoided building additional scheduling behavior on top of a faulty assumption.
The application could reliably translate between UTC and TAI/J2000 while accounting for the nuances that a fixed offset ignored. More importantly, the conversion became isolated, testable, and understandable rather than remaining an implicit assumption buried inside scheduling logic.
The experience reinforced several principles I still carry into precision-sensitive systems:
- Treat foundational assumptions as things to verify, not inherit.
- Isolate complicated domain logic behind clear boundaries.
- Test the uncomfortable edge cases, not just today’s expected input.
- Make critical behavior deterministic.
- Build observability and validation into the workflow.
- Use tools—including AI—to accelerate reasoning, not replace verification.
The actual code required to convert one representation of time into another wasn’t the most important part of the work.
The important part was recognizing that time itself was part of the domain model and onnce that became clear, correctness wasn’t an implementation detail anymore. It was the feature.
More Case Studies
Different problems, different constraints, and different kinds of solutions. Here’s another project from the collection.
Have a Complicated Problem of Your Own?
If you’re working with a system where the details really matter—or you’ve run into a problem that doesn’t have an obvious answer—I’d be happy to hear about it. You don’t need to know the solution before reaching out. Figuring that part out is often the most interesting part of the work. Send me a message below or reach me directly at mitchell@betavc.com