Skip to content
Workflow Automation

Pontes Is Live: Designing A Settlement Workflow That Survives Atomic DvP, Two Cash Rails And A Central Bank That Only Confirms Finality In T2

On 21 September the Eurosystem switched on Pontes, the bridge that lets tokenised wholesale transactions on market DLT platforms settle their cash leg in central-bank money - with Deutsche Bank, Santander, Société Générale, KfW and the EIB in the first wave alongside four ledger operators including Clearstream. The design is precise: two cash routes, cash tokens on the Eurosystem's own DLT or ordinary T2, and in both cases finality only when the T2 leg completes; a Hash-Link protocol for delivery-versus-payment and any other all-or-none settlement; access restricted to T2 participants, authorised CSDs, DLT pilot-regime operators, payment systems and CCPs. The UK's six-bank sterling pilot proved the deposit-token model; Britain's digital gilt is being issued on HSBC Orion. What none of the announcements cover is the workflow code that has to orchestrate an atomic asset leg against a cash leg whose finality arrives from a different system - and what to do when it does not.

AlchmAI Engineering15 min read

21 Sept

Pontes initial launch: DLT platforms connected to TARGET Services so wholesale tokenised transactions settle in central-bank money

2 routes

Cash tokens on the Eurosystem DLT, or T2 - and either way the cash leg is final only once the T2 transaction completes

Hash-Link

The interoperability protocol Pontes uses for delivery-versus-payment and other all-or-none settlements across platforms

6 banks

Barclays, HSBC, Lloyds, NatWest, Nationwide and Santander in the UK's live tokenised sterling pilot, with the digital gilt on HSBC Orion

Every settlement system ever built has one job that everything else exists to protect: make sure the asset moves if and only if the cash moves. Pontes, which the Eurosystem launched on 21 September, is the first production central-bank infrastructure in a major currency that lets the asset leg live on a market DLT platform while the cash leg settles in central-bank money - and its design says something specific about where finality lives. There are two cash routes: settlement on the Eurosystem's own DLT platform with cash tokens, or settlement in T2, the real-time gross settlement system. In both cases, in the ECB's words, final settlement in central-bank money for the cash leg is achieved once the corresponding transaction is completed in T2. The asset leg on the market platform is synchronised through the Hash-Link protocol, which supports delivery-versus-payment and other transactions requiring all-or-none settlement.

The first wave is not experimental: Deutsche Bank, Santander, Société Générale, KfW and the European Investment Bank, with four ledger operators including Clearstream. Eligible participants must hold T2 access, and eligible DLT operators are authorised CSDs, DLT pilot-regime operators, EU payment systems, CCPs and licensed institutions meeting Eurosystem supervision criteria. Improvements arrive step by step. Across the Channel, the UK's six-bank live sterling pilot on Quant's infrastructure tested marketplace payments, remortgaging and digital-asset settlement, and HM Treasury selected HSBC Orion in February as the platform for DIGIT, the digitally native gilt issued inside the Digital Securities Sandbox. The tokenised-settlement world now has production rails in both jurisdictions.

The Shape Of An Atomic Leg Pair

A hash-lock DvP has a recognisable sequence regardless of platform. The delivering party locks the asset on the DLT platform against a hash H of a secret S, with a time-out. The paying party observes the lock and initiates the cash leg conditioned on the same H. When the cash leg is final, S is revealed; the asset unlocks to the buyer. If S is never revealed before the time-out, the lock expires and the asset returns. Pontes fits that shape with one important specific: the moment the paying party may treat cash as final is the T2 completion, whichever route was chosen.

pythonsettlement/dvp_workflow.py
from datetime import timedelta
from temporalio import workflow, activity
from temporalio.common import RetryPolicy

@workflow.defn
class DvPSettlementWorkflow:
    """One instrument, one cash amount, one counterparty, atomic or nothing.
    Every side-effecting step is an activity with an idempotency key derived
    from the workflow id, because the engine WILL retry across a crash."""

    @workflow.run
    async def run(self, trade: TradeLeg) -> SettlementOutcome:
        wf_id = workflow.info().workflow_id
        secret_hash = await workflow.execute_activity(
            mint_hash_lock, trade.trade_id, start_to_close_timeout=timedelta(seconds=10))

        # 1. ASSET LEG: lock on the market DLT platform against H, with a time-out
        #    comfortably longer than the cash route's worst-case T2 completion.
        lock = await workflow.execute_activity(
            lock_asset_on_platform,
            LockRequest(trade=trade, secret_hash=secret_hash.h,
                        expires_at=workflow.now() + timedelta(minutes=trade.lock_minutes),
                        idempotency_key=wf_id + ":lock"),
            start_to_close_timeout=timedelta(seconds=60),
            retry_policy=RetryPolicy(maximum_attempts=5))

        # 2. CASH LEG: instruct via Pontes on the chosen route. The instruction is
        #    conditioned on H; nothing is final yet.
        cash = await workflow.execute_activity(
            instruct_cash_leg,
            CashInstruction(trade=trade, route=trade.cash_route,   # "dlt_cash_token" | "t2"
                            secret_hash=secret_hash.h,
                            idempotency_key=wf_id + ":cash"),
            start_to_close_timeout=timedelta(seconds=60),
            retry_policy=RetryPolicy(maximum_attempts=5))

        # 3. WAIT FOR T2 FINALITY. Not the platform's view - T2's. A durable timer
        #    bounds the wait to the lock's life; a signal delivers the confirmation.
        try:
            final = await workflow.wait_condition(
                lambda: self._t2_final is not None,
                timeout=lock.expires_at - workflow.now() - timedelta(seconds=30))
        except TimeoutError:
            # Cash never became final inside the lock window. The asset lock will
            # expire on its own; record it, do NOT reveal the secret, and unwind
            # the cash instruction explicitly - a cancel, not a rollback.
            await workflow.execute_activity(cancel_cash_instruction, cash.reference,
                start_to_close_timeout=timedelta(seconds=60), retry_policy=RetryPolicy(maximum_attempts=10))
            return SettlementOutcome(status="unsettled_timeout", lock=lock, cash=cash)

        # 4. REVEAL S -> asset unlocks to the buyer. Idempotent: revealing twice is harmless.
        await workflow.execute_activity(
            reveal_secret_on_platform, RevealRequest(lock_id=lock.id, secret=secret_hash.s,
                                                     idempotency_key=wf_id + ":reveal"),
            start_to_close_timeout=timedelta(seconds=60), retry_policy=RetryPolicy(maximum_attempts=10))

        await workflow.execute_activity(record_settlement, SettlementRecord(
            trade=trade, lock=lock, cash=cash, t2_reference=self._t2_final.reference,
            t2_final_at=self._t2_final.at), start_to_close_timeout=timedelta(seconds=30))
        return SettlementOutcome(status="settled", lock=lock, cash=cash, t2=self._t2_final)

    _t2_final: T2Final | None = None

    @workflow.signal
    async def t2_finality(self, final: T2Final) -> None:
        # Delivered by the listener that watches T2 confirmations - the ONLY
        # source your workflow accepts for "the cash is final".
        self._t2_final = final

Compensation Is An Unwind, Not A Rollback

Durable execution gives you sagas, and settlement is where the saga pattern shows its teeth. A cash instruction that has been accepted cannot be un-sent; it can be cancelled if it has not completed, and reversed by a new instruction if it has. An asset lock cannot be deleted; it expires or it is released. And the case that has no clean compensation - cash final in T2, reveal failing on the platform for longer than the lock window - is the one to design for explicitly, because it is the one where the buyer has paid and does not hold the asset.

  1. 01Time the lock to the cash route, with margin. The lock window must exceed the worst-case time to T2 finality on the chosen route plus the time to reveal. Measure both from production telemetry; do not assume.
  2. 02Make reveal the most-retried activity in the system. It is idempotent and it is the step whose failure strands a paid-for asset. Ten attempts with backoff is not excessive.
  3. 03If reveal is still failing as the lock nears expiry, escalate to a human before expiry, not after. The workflow should park with the full context - trade, lock, T2 reference - and page, because the decision that follows is a business one about a counterparty.
  4. 04Reconcile the three ledgers - your book, the platform, T2 - on every outcome, not just settled ones. An unsettled_timeout with a cash cancel that itself failed is a break you want to find in minutes.
  5. 05Never compensate by revealing. The temptation when cash has failed is to release the lock 'to be tidy' by revealing S. Revealing S delivers the asset. The lock expiring is the correct release.

Two Cash Rails, One Workflow

The choice between cash tokens on the Eurosystem DLT and plain T2 is a routing decision the workflow should make from data, not a fork in the code. The cash route affects the instruction format and the expected finality latency; it does not change the leg-pair logic. Encode the route as data on the trade, keep the finality listener the same for both, and the same workflow settles either. The UK case is structurally identical: a sterling deposit token on a bank's platform against a DIGIT on HSBC Orion is an asset leg and a cash leg with a finality source, and the workflow shape carries across with different adapters.

pythonsettlement/routes.py
from dataclasses import dataclass

@dataclass(frozen=True)
class CashRoute:
    name: str
    instruct: callable          # builds the instruction for this rail
    expected_finality: str      # ISO 8601 duration, from measured telemetry
    finality_source: str        # MUST be a T2 confirmation for either Pontes route

ROUTES = {
    "dlt_cash_token": CashRoute("dlt_cash_token", build_dlt_cash_instruction, "PT2M", "t2_confirmation"),
    "t2":             CashRoute("t2",             build_t2_instruction,       "PT5M", "t2_confirmation"),
    # UK sterling deposit token rail; finality from the issuing bank's ledger
    # confirmation, which is a DIFFERENT source and is modelled as such.
    "gbp_deposit_token": CashRoute("gbp_deposit_token", build_gbtd_instruction, "PT1M", "issuer_ledger_confirmation"),
}

def lock_window_for(route: CashRoute, reveal_budget: str = "PT3M") -> str:
    # Lock must outlive worst-case finality plus the reveal budget, with margin.
    return add_durations(route.expected_finality, reveal_budget, "PT5M")

What Changes In The Systems Around The Workflow

  • The overnight reconciliation window shrinks toward zero. Atomic settlement removes the delay in which most firms currently catch their own errors. Reconciliation becomes continuous, per outcome, or it becomes too late.
  • Liquidity management moves intraday. Cash that settles in minutes against assets on a platform has to be positioned in minutes; treasury tooling built for end-of-day netting needs an intraday view of tokens and T2 balances together.
  • Custody and entitlement span two ledgers. Who may instruct a lock, who may instruct cash, and who may see either are now questions across the platform and T2 access - the same two-rail entitlement problem as the compliance side of tokenised money.
  • Audit needs three references per settlement. Your trade id, the platform lock id, the T2 reference. Store all three on the record; a settlement that cannot be traced across all three systems cannot be defended.
  • The finality listener is critical infrastructure. If it is down, no settlement completes even though cash is moving. It needs the same resilience treatment as the OMS and a place on the important-business-service map.

The Bottom Line

Pontes went live on 21 September with Deutsche Bank, Santander, Société Générale, KfW and the EIB, and it made a design choice every settlement workflow now has to respect: two cash routes, one finality source, and that source is T2. Hash-Link gives you atomic delivery-versus-payment across platforms; your workflow gives you atomicity under failure, and it does so by treating the asset lock and the cash finality as events from different systems, waiting for finality from the one source allowed to declare it, making the reveal the most-retried and most-escalated step in the system, and compensating with cancels and unwinds rather than pretending a reversal exists. Route the cash as data so the same workflow settles on either rail - or on a sterling deposit token against a gilt on Orion - keep three references on every record, and move reconciliation and liquidity to intraday because the overnight window that hid mistakes is gone. That is the settlement workflow engineering we build for financial institutions in London, and with production rails now live in both the euro area and the UK, it has stopped being a pilot skill.

References & Further Reading

Workflow automation code samplesWorkflow Automation Agency architecturePontesatomic settlementTrading Workflow architectureWorkflow Automation Londontokenised deposits
Share Email
AI

AlchmAI Engineering

Engineering, London

Written by the AlchmAI engineering team in Mayfair, London. We build trading platforms, real-time charts, market data pipelines and AI features for brokers, prop firms and fintech teams. The Playbook is where we explain how we approach these systems, with code you can run and sources you can check.

Code in this guide is illustrative and supplied without warranty. Review and test it before production use. Nothing here is investment advice. Important information