Self-service terminals at national scale
The TypeScript UI and channel service orchestration layer for in-branch self-service kiosks, deployed across 880+ branches serving 24M+ customers.
Overview
I contributed to the development and ongoing technical support of self-service terminals deployed across the branch network of one of South Africa's largest retail banks. These in-branch kiosks handle account management, document generation, card services, and biometric verification for millions of customers daily.
My role spanned two areas: building the TypeScript terminal UI and developing the channel service layer that orchestrates communication between the terminal front-end and backend product services. This was team-delivered work within a multi-team channel division.
Architecture
The platform follows a layered architecture separating presentation, orchestration, and domain logic.
Terminal UI layer
Built in TypeScript for constrained kiosk hardware. Touch-optimised, low cognitive load, accessible across varying digital literacy levels, and fast to render on limited hardware. Deliberately kept thin: presentation and input capture only, with business logic delegated to the channel service layer.
Channel service layer
The orchestration and resilience boundary:
- Request routing: directing terminal requests to the right product service endpoints
- Retry logic: configurable policies with exponential backoff to avoid cascading load
- Timeout management: strict timeouts per service call to prevent terminal hangs
- Response transformation: normalising responses into a consistent UI contract
- Session context: maintaining state across multi-step flows
Engineering challenges
Resilience in a physical environment
A kiosk failure means a customer standing at a broken screen. The channel service handles downstream timeouts, provides meaningful fallback states, and makes sure partial failures do not leave inconsistent state.
Network variability
880+ branches, with network conditions that vary nationally. Timeouts are tuned per service call type, and retry policies balance user experience against system load.
Hardware integration
Card readers, biometric scanners, and printers, with firmware inconsistencies across terminal batches and graceful handling when a peripheral failed mid-interaction.
Technologies
| Front-end | TypeScript, touch-optimised kiosk UI |
| Orchestration | Channel service layer, retry policies, timeout management |
| Patterns | Exponential backoff, graceful degradation, session management |
| Integration | Card readers, biometric scanners, printers |
| Scale | 880+ branches, 24M+ customers |
Key takeaways
The channel service pattern proved essential. By keeping the UI thin and centralising orchestration, we could evolve backend integrations without redeploying to every terminal.
Supporting at this scale sharpened diagnostic skills. When a terminal fails 1,000km away, you need detailed logging, clear error taxonomies, and the ability to reason about failure modes from telemetry alone.