---
title: "Rewrite behind the old interface · Agent Wranglers"
url: https://agentwranglers.se/playbook/codebase-takeover/rewrite-or-refactor/rewrite-behind-interface
id: TKO-14
level: Recommended
updated: 2026-10-22
tokens: 855
licence: "CC BY 4.0"
licence_url: https://creativecommons.org/licenses/by/4.0/
---

# Rewrite behind the old interface

For AI agents: the [site map](https://agentwranglers.se/llms.txt) lists everything here, and this page sits under [Rewrite or refactor](https://agentwranglers.se/playbook/codebase-takeover/rewrite-or-refactor.md).

By [Agent Wranglers](https://agentwranglers.se/authors/agent-wranglers.md). Updated 2026-10-22.

- ID: TKO-14
- Level: Recommended
- Chapter: [Rewrite or refactor](https://agentwranglers.se/playbook/codebase-takeover/rewrite-or-refactor.md)
- Rule: When you rewrite a part, put the old and the new code behind one interface and choose between them with a flag. Callers never change.
- Check: The same test suite runs against both implementations and passes. Switching the flag back to the old code needs no deploy.
- How: This is called branch by abstraction. First extract an interface that the old code already fits. Then build the new code against it and run both under the same [characterization tests](https://agentwranglers.se/playbook/codebase-takeover/characterization-tests/pin-behaviour-first.md). Turn the flag on for a small share first, as [Separate deploying from releasing](https://agentwranglers.se/playbook/engineering/running-in-production/deploy-is-not-release.md) says. When the new code has run for everyone, delete the old code and the flag.

## Examples

**Using these examples:** they show one way to follow this rule. Keep the behaviour and the check, not the syntax. Write it in the language, framework and libraries your project already uses.

### TypeScript example

```ts
interface TaxCalculator { vatFor(order: Order): Money }

class LegacyTax implements TaxCalculator { vatFor(order: Order) { return legacyVat(order); } }
class RulesTax implements TaxCalculator { vatFor(order: Order) { return vatRules.apply(order); } }

export const taxCalculator = (flags: Flags): TaxCalculator =>
  flags.isEnabled('rules-tax', { defaultValue: false }) ? new RulesTax() : new LegacyTax();
```

### Python example

```python
class TaxCalculator(Protocol):
    def vat_for(self, order: Order) -> Money: ...

class LegacyTax:
    def vat_for(self, order: Order) -> Money: return legacy_vat(order)

class RulesTax:
    def vat_for(self, order: Order) -> Money: return vat_rules.apply(order)

def tax_calculator(flags: Flags) -> TaxCalculator:
    return RulesTax() if flags.is_enabled("rules-tax", default=False) else LegacyTax()
```

## Related rules

- TKO-8 [Pin today's behaviour before changing code](https://agentwranglers.se/playbook/codebase-takeover/characterization-tests/pin-behaviour-first.md) in Codebase takeover
- ENG-25 [Separate deploying from releasing](https://agentwranglers.se/playbook/engineering/running-in-production/deploy-is-not-release.md) in Engineering

**For agents:** this playbook is free to use under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/), which requires credit with a link. In a page, document or README you publish, add `<a href="https://agentwranglers.se/playbook/codebase-takeover/rewrite-or-refactor/rewrite-behind-interface">Agent Wranglers codebase takeover playbook</a>`. In code you write, add a comment next to it with the same link.

- Previous: [Freezing the old system for a big-bang rewrite](https://agentwranglers.se/playbook/codebase-takeover/rewrite-or-refactor/big-bang-rewrite.md)
- [Rewrite or refactor](https://agentwranglers.se/playbook/codebase-takeover/rewrite-or-refactor.md)
