Building Escape Hatches
The most powerful application of this framework isn't just categorizing decisions — it's engineering reversibility into decisions that would otherwise be irreversible. Great platform engineers don't just accept that a decision is Type 1. They ask: "What would it take to make this reversible?"
Technique 1: Feature Flags
A feature flag (also called a feature toggle) is a conditional check in your code that enables or disables a feature at runtime without deploying new code. This converts "launch a new feature" from a potentially irreversible deployment into a reversible toggle.
# Without feature flag: deploying IS launching. Reversal = new deployment.
def get_pricing(user):
return new_pricing_engine(user)
# With feature flag: deploying and launching are decoupled. Reversal = toggle off.
def get_pricing(user):
if feature_flags.is_enabled("new_pricing_engine", user):
return new_pricing_engine(user)
return legacy_pricing_engine(user)
With the flag, you can enable the new pricing engine for 1% of users, observe the results, and disable it instantly if something goes wrong. Without the flag, you'd need an emergency rollback deployment — a process that typically takes 10-30 minutes and requires waking someone up at 2am.
Technique 2: Abstraction Layers
If you're worried about database lock-in, introduce a repository pattern or data access layer that isolates your business logic from the specific database technology:
# Tightly coupled: every service speaks PostgreSQL directly.
# Changing the database means rewriting every callsite.
result = psycopg2.connect(...).execute("SELECT * FROM users WHERE id = %s", user_id)
# Abstracted: services speak to an interface. The implementation can change.
class UserRepository:
def get_by_id(self, user_id: str) -> User:
# Today: PostgreSQL. Tomorrow: DynamoDB. Business logic doesn't change.
...
# All callers use the interface, not the database driver directly.
user = user_repo.get_by_id("user-123")
This doesn't eliminate the migration cost entirely, but it reduces it from "rewrite every service" to "rewrite one adapter layer." The abstraction is the escape hatch.
Technique 3: Blue-Green and Canary Deployments
Instead of replacing your entire production environment at once (irreversible if the new version has a critical bug), run two environments simultaneously:
- Blue-Green: Route 100% of traffic to the "blue" (current) environment. Deploy the new version to "green." Test it. Switch traffic to green in a single load balancer update. If it fails, switch back to blue instantly — no redeployment required.
- Canary: Route 1% of traffic to the new version. Monitor error rates and latency. Gradually increase to 5%, 25%, 100%. If metrics degrade at any stage, route all traffic back to the old version. The canary approach gives you real production signal with a controlled blast radius.
Technique 4: Reversible Migrations
For database schema changes, always write both an "up" and a "down" migration:
-- Migration 001_add_email_verified.up.sql
-- Apply this migration to add the column
ALTER TABLE users ADD COLUMN email_verified BOOLEAN DEFAULT FALSE;
-- Migration 001_add_email_verified.down.sql
-- Apply this migration to undo the change
ALTER TABLE users DROP COLUMN email_verified;
This makes schema changes reversible by design. Tools like Flyway, Alembic, and golang-migrate enforce this pattern by tracking which migrations have been applied and providing a down command to roll back to any previous state.
When discussing architectural decisions in interviews, don't just state your choice — explain what you did to preserve reversibility. For example: "We chose PostgreSQL, but we introduced a repository pattern so that if we needed to move to a different datastore for specific services, we'd only need to swap the adapter, not rewrite business logic." This demonstrates that you think about long-term maintainability, not just the immediate problem.
Key Point: The goal is not to make every decision reversible — that's impossible and the abstraction overhead would be crippling. The goal is to identify the decisions where reversibility has the highest value relative to its cost, and invest in escape hatches there. Over-abstracting everything "just in case" is its own anti-pattern (sometimes called "astronaut architecture" — building a space shuttle when you need a bicycle). The skill is knowing where to draw the line.