One of the easiest ways to describe LayoverGuard is with a sentence that sounds complete:
If the incoming flight reaches the gate late enough, trigger the fixed payout.
The problem is that software does not know what you meant by that sentence.
It needs to know exactly who qualifies, which version of the journey matters, when a decision becomes valid, what happens if something changes after purchase, and which situations should result in a payout, a refund, no action, or no offer in the first place.
The happy path usually fits into one sentence. The product does not.
This has been one of the more interesting lessons for me while building LayoverGuard. Before you can automate a product, you have to define the promise precisely enough that a system can apply it consistently.
Otherwise, automation does not remove ambiguity.
It just processes ambiguity faster.
The happy path is usually already obvious
Most product ideas are easy to explain when everything goes as expected.
A traveler has an eligible journey. The product is available. The traveler purchases it. A qualifying event later occurs. The fixed payout follows.
There is not much engineering philosophy hidden in that sequence.
The difficult questions begin when reality moves away from the happy path.
What if the underlying journey changes after purchase? What if information that mattered when the product was offered looks different at purchase time? What if the event data arrives late? What if the system can observe that something changed but cannot yet determine the final state?
These are not necessarily rare edge cases in the traditional software sense. They are often normal consequences of depending on a real-world system that keeps changing.
Airlines update schedules. Travelers change bookings. Operational data evolves over time. External systems update asynchronously. The thing you evaluated yesterday may not look exactly the same tomorrow.
Determining what actually happened to the flight is a separate problem in itself, which I wrote about in A Flight Delay Is Not a Boolean.
At that point, the product needs more than a good headline.
It needs rules.
Eligibility is part of the product
Engineers often encounter eligibility as validation logic.
eligible = true
or:
return OFFERED
It is easy to look at rules like these as implementation details sitting behind the real product.
I increasingly think that is the wrong way to look at them.
Eligibility is part of the product itself because it defines where the promise begins and where it does not.
If a journey qualifies under one set of circumstances but not another, that distinction needs to exist before the API response. The software is only expressing a product decision that someone already had to make.
And those decisions can interact.
A rule may make perfect sense by itself but create unexpected behavior when combined with timing, schedule changes, existing exposure, or another rule.
This is where product work starts to look less like writing requirements and more like building a model of the world.
The model will always be simpler than reality. The question is whether it is simple in the right places.
Time changes the meaning of a decision
One thing that keeps appearing in travel products is that the same journey can mean different things depending on when you look at it.
Suppose a system evaluates a journey several weeks before departure.
At that moment, it has one schedule, one set of known conditions, and one view of the journey.
Later, the schedule changes.
Closer to departure, more operational information becomes available.
Eventually, the flight is operating in real time.
These are all observations of the same journey, but they are not equivalent product moments.
A decision made weeks before departure cannot always be treated as though the system is evaluating the journey for the first time moments before purchase. Likewise, something that happens after purchase should not silently rewrite what the customer was shown earlier.
This forces the system to answer a surprisingly important question:
When did this decision become true?
That question affects what needs to be stored.
If you only persist the latest version of everything, you may know what the world looks like now but lose the context in which an earlier decision was made.
Sometimes the history of a value matters as much as the value itself.
That is a very different problem from simply fetching the latest record from an API.
Product states matter more than they first appear
Another thing I have come to appreciate is how quickly a simple product becomes a state-management problem.
At first, you may imagine only a few states:
OFFERED
PURCHASED
PAID
Reality usually adds more.
A quote can expire. A purchase can remain active while the underlying journey changes. An event may be observed but not yet final. A transaction may need to end without ever reaching the payout state.
The names are implementation-specific, but the broader lesson is not.
A product needs to know not only what happened, but also what is allowed to happen next.
This sounds like classic state-machine design, and technically it is. But each transition also represents a product decision.
Can this state move to that state?
Who or what is allowed to cause the transition?
Can it happen twice?
Can it be reversed?
What if two systems try to cause different transitions at nearly the same time?
Once money is attached to those transitions, these are no longer abstract architecture questions.
They are part of how the product behaves.
Automation makes ambiguity more expensive
There is a common assumption that automation simplifies a process.
For the customer, that can absolutely be true.
For the system, it often means the opposite.
A manual process can tolerate a surprising amount of ambiguity because a person can interpret the situation later. They can look at the context, ask another question, or decide that something unusual deserves special handling.
Software cannot improvise unless you explicitly design a way for it to do so.
That means automation pushes decisions earlier.
Before an unusual case happens, someone has to decide what the system should do when it happens.
Before an event can lead automatically to a financial outcome, the system needs to know what evidence is sufficient.
Before an instant quote can be returned, the system needs to know which conditions make the product available.
Software cannot fix an ambiguous product promise. It can only automate the ambiguity faster.
That idea has become increasingly important to me as we build more of the product.
The implementation keeps sending us back to product
Earlier in my career, I probably thought about the relationship between product and engineering in a fairly sequential way.
Product defines what should happen.
Engineering figures out how to make it happen.
There is obviously iteration between the two, but the direction still feels mostly clear.
Building LayoverGuard has made that loop much tighter.
We define a rule. Engineering begins implementing it. The implementation exposes a situation that was not obvious in the original product discussion.
Now there is a new product question.
The answer may create a new data requirement. That requirement may change what needs to be persisted at purchase time. That change may expose another situation we need to think through.
So the cycle becomes something closer to:
product → implementation → new question → product → implementation
I no longer see those loops as evidence that the original specification was bad.
In many cases, they are how the product becomes precise.
There is a limit to how much you can discover by discussing a system in the abstract. Eventually, you have to build enough of it for the inconsistencies to become visible.
Rules are also boundaries
There is another reason clear rules matter: they prevent the product from quietly becoming something different over time.
When you are building quickly, there is always a temptation to handle one more situation.
A new case appears, so you add another exception.
Then another.
Eventually, the implementation may support a broader set of behaviors than the original product was designed around.
That can make the software more flexible while making the product less coherent.
We are still learning where some of those boundaries should be for LayoverGuard, and I am intentionally not describing our specific eligibility, timing, or decision rules here.
But the principle has become important to me.
A good rule does not only tell the system when to say yes.
It also makes it clear when the product should say no, wait, or do nothing.
Those boundaries are part of the product.
Product and technology are not separate layers
This may be the part that feels most relevant to my role now.
As a CPTO, I spend a lot of time moving between questions that would traditionally be labeled either product or technology.
Should the customer see this state?
What information should exist at purchase time?
What happens when an external system changes something?
Should the system make a decision now or wait?
What should another system be allowed to tell us?
Some of those sound like product questions. Others sound like engineering questions.
In practice, they often describe the same decision from two different directions.
A product promise eventually becomes data, state, conditions, and transitions.
And software architecture eventually determines which product promises are practical to make reliably.
That relationship is much tighter than I appreciated before building a product where automated decisions can directly lead to financial outcomes.
We are still defining parts of it
I do not want to give the impression that every LayoverGuard rule is final.
It is not.
We are still building, testing assumptions, and finding places where the product model needs to become more precise. I expect some decisions will change as the system encounters more real-world situations.
But I think that is exactly why this stage is interesting.
At the beginning, a product is mostly described in sentences.
As it becomes real, those sentences have to turn into decisions that can be repeated thousands of times without someone standing next to the system explaining what was originally intended.
That is when you find out whether the promise was actually defined.
Automation comes after that.
Or at least, I am increasingly convinced that it should.