Bespoke software

Software you can trust.

We build complex systems for businesses using domain-driven design and formal verification. Your business rules are designed, specified and checked before they reach production.

bookings.specIllustrative
MODEL  Booking
  states  requested → held → paid → confirmed
                                ↘ cancelled

INVARIANT  NoDoubleBooking
  ∀ a, b ∈ confirmed :
    a.room = b.room ⇒ ¬ overlaps(a.slot, b.slot)

INVARIANT  PaidBeforeConfirmed
  ∀ b ∈ confirmed : paid(b)

CHECK  every reachable state
  ✓ NoDoubleBooking       holds
  ✓ PaidBeforeConfirmed   holds

Why it matters

Most expensive software failures don’t come from typos in the code. They come from gaps in understanding.

Complex systems fail at the edges: two payments landing at once, a booking that’s half cancelled, a rule that made sense to one department and not to another.

Tests only check the cases someone thought of. We aim to remove whole classes of failure before they can happen. We model the business precisely, then prove the design behaves.

“Program testing can be used to show the presence of bugs, but never to show their absence.”

Edsger W. Dijkstra

Our approach

From a shared model to proven, production-ready code.

Domain-driven design makes sure we’re building the right thing. Formal verification makes sure we’re building it right.

  1. Map the domain

    We run workshops with the people who run the business. Together we capture the language, the processes and the edge cases, and turn them into a domain model everyone agrees on.

    • Event storming
    • Ubiquitous language
    • Bounded contexts
  2. Specify the rules

    We write down the rules that must always hold, precisely. Balances reconcile. Stock never goes negative. Approvals happen in the right order. Nothing is left as tribal knowledge.

    • Invariants
    • State machines
    • Formal specification
  3. Verify the design

    Before we build, we check the design against every state it can reach, using model checking and property-based testing. For the most critical logic, we add machine-checked proofs.

    • Model checking
    • Property-based testing
    • Proofs
  4. Build it properly

    We write clean, strongly typed code that mirrors the model. The specification carries through into automated tests, so the code and the rules can’t quietly drift apart.

    • Type-driven design
    • Automated tests
    • CI/CD
  5. Keep it trustworthy

    The model stays as living documentation. That makes change safe for us, for your team, and for whoever works on the system next.

    • Living documentation
    • Safe change
    • Handover

Where we work

Built for complicated rules and lots of moving parts.

  • Payments, billing & ledgers

    Money that always adds up, even with concurrency, retries and partial failures.

  • Booking & scheduling

    No double bookings, no impossible states and no overnight clean-up scripts.

  • Workflows & approvals

    Multi-step processes where order, permissions and a reliable audit trail matter.

  • Regulated & compliance-heavy systems

    Where you need to show that the rules are enforced, as well as say so.

  • B2B platforms & integrations

    Multi-tenant platforms, and integrations between systems that were never designed to talk to each other.

  • Untangling existing systems

    We document and model complex legacy systems so you can change them with confidence.

What you get

More than code.

Every engagement leaves you with a system you can explain, evidence that it works, and a team that can safely build on it.

  • A domain model your whole team understands
  • A precise specification of your critical business rules
  • Verification results you can show to stakeholders and auditors
  • Production-ready, tested and documented code
  • A system that stays safe to change

Building something complex?

Let’s model it together.

Tell us about the system, whether it’s new or already in production and causing trouble. We’ll come back with how we’d approach it.

Start the conversation