Infrastructure & Reliability · Middleware — Web · Chapter 21 of 33
The web tier in a bank: real flows, real failures
Internet banking, partner APIs and staff applications traced through the tiers — the four failures behind most incidents, how patching is done without an outage, and the javax-to-jakarta migration every Java estate is working through.
The previous chapter was mechanics. This one follows three real kinds of traffic through a bank’s web estate, then turns to what actually breaks, and to the change work — patching and one large migration — that fills a middleware team’s calendar.
Flow 1 — a customer logs in to internet banking
- Edge. The request first reaches a content delivery network or a denial-of-service protection service, which absorbs floods of junk traffic before they reach the bank at all.
- Web application firewall. A web application firewall (WAF) inspects the request for known attack patterns — injection attempts, malformed headers — and blocks them.
- Web tier. TLS is terminated; the request is passed to the application tier, usually re-encrypted so traffic inside the bank is not readable on the wire either.
- Application tier. The login application checks the password against the identity service and triggers a second factor. The design of that step is in MFA architecture — multi-factor authentication.
- Back end. The landing page needs balances. The application either calls an internal API or puts a request on an IBM MQ queue in front of the core banking system and waits for the reply — the request/reply pattern covered in the messaging chapters.
A useful interview habit: give each hop a latency budget. If the page must render in 800 milliseconds, the edge and firewall might take 50, the web tier 20, identity and the second factor 300, the balance lookup 250, and page assembly the rest. When the page is slow, the budget tells you which team to call — and each tier’s logs, joined on a request identifier passed along every hop, tell you whether the budget was broken.
Flow 2 — a partner calls the bank’s API
A fintech, a corporate client or another bank calls an API rather than a web page, so there is no person to type a password. The two sides prove their identities with certificates in both directions: mutual TLS (mTLS), in which the client presents a certificate as well as the server. The bank issues or approves each partner’s certificate and the web tier refuses any connection without one.
The operational consequence is easy to miss. Every partner certificate has its own expiry date, managed by someone outside the bank. A partner that forgets to renew breaks its own integration, but it arrives at the bank as an incident — so the bank’s certificate inventory has to track certificates it does not control, and warn the partner, not only itself.
Flow 3 — a branch or operations application
Staff systems are often the oldest part of the estate: large Java applications written for a full application server, using its transaction manager, its messaging and component models such as Enterprise JavaBeans (EJB). They work, they are rarely rewritten, and they are the hardest to move — because the code depends on the server’s services, not just on its ability to answer HTTP. When a bank says its modernisation is stuck, this is usually where.
What actually breaks
Certificate expiry is the classic because it is the only outage that arrives on a date printed inside the thing that fails. The mechanics, and the industry outages it has caused, are in TLS. The control is unglamorous: a complete inventory — web servers, load balancers, application servers, queue-manager channels, file-transfer endpoints, partner certificates — with renewal automated wherever the issuing process allows it.
Pool exhaustion was the subject of Little’s law in the previous chapter: a dependency slows, threads wait, the pool fills, and everything queues. It is the most common cause of “the site is slow but every system reports healthy”.
Memory and garbage collection. Java frees memory automatically with a garbage collector, which periodically pauses or slows the application to reclaim objects no longer in use. As the heap — the memory the Java Virtual Machine (JVM) manages — fills with objects that are still referenced (a leak, an oversized cache, a huge result set), collections run more often and pause longer, until the process fails with an OutOfMemoryError. The early signal is in the garbage-collection log, days before the failure; the evidence afterwards is a heap dump, which the JVM can be told to write automatically when it runs out.
Drift and bad change. Two production nodes that are supposed to be identical, and are not, because someone changed one by hand during an incident a year ago. The control is to build every node from configuration held as code, so any difference is visible in version control.
Patching without an outage
A bank web estate absorbs a steady stream of mandatory change: operating-system patches, web-server and application-server fix packs, and Java updates — Oracle ships Critical Patch Updates for Java every quarter, in January, April, July and October, and other Java distributions follow a similar rhythm. The technique that makes this routine is a rolling change:
- Take one node out of the load balancer and drain it, letting in-flight requests finish.
- Patch it, restart it, and run the readiness check.
- Return it to the pool as a canary — a small share of live traffic, watched closely — before touching the next node.
- Repeat, never taking out more capacity than the remaining nodes can carry at peak.
Two constraints shape the calendar. Change freezes — around quarter-end, financial year-end and peak retail periods such as festival season in India — forbid non-emergency change, so patches queue up before them. And sessions: if they live in one server’s memory, every rolling patch logs customers out, which is why session design belongs to the middleware conversation.
The migration of the decade: javax to jakarta
When Oracle handed Java EE to the Eclipse Foundation in 2017, it kept the rights to the javax package names. The specifications could not evolve under a name the new owner did not control, so Jakarta EE 9, released on 8 December 2020, renamed every package from javax.* to jakarta.* and changed nothing else. It was a release designed purely to break compatibility once, so that the platform could move again.
For a bank the consequence is concrete: every Java class that imports an enterprise API changes, and so must every library it uses. An application cannot mix the two worlds, so the move is an application migration, not a server upgrade. Tools — the Eclipse Transformer, OpenRewrite recipes and the vendors’ own migration toolkits — automate most of the renaming; testing is the expensive part.
The trap in ‘no planned end of support’
IBM’s lifecycle page states that there is no planned end-of-support date for WebSphere Application Server traditional 8.5 and 9.0 — earlier IBM guidance had said “through at least 2030”. That removes the server as a forcing deadline, and it is easy to read as permission to stay.
The deadline arrives from the libraries instead. Spring Boot 3, released in November 2022, requires the jakarta namespace and Java 17, and the 2.x line no longer receives open-source fixes. An application that must stay on a javax-only server gradually loses access to maintained versions of the libraries around it — a debt that grows quietly while the server itself is fully supported.
Where this is heading: the shared server dissolves
The classic model was one large, shared application server hosting dozens of applications, owned and patched by the middleware team. The modern model inverts it: each application carries its own small server — an embedded Tomcat inside a Spring Boot application, WebSphere Liberty or Quarkus in a container — and is deployed on a container platform such as Red Hat OpenShift or another Kubernetes distribution (see Kubernetes).
The middleware team does not disappear; its job moves. It owns the base images every application is built from, the platform, the certificates, the Java runtime and its licensing, and the shared services that are still shared — above all the messaging layer. And one application server predates all of this and still runs the core of many banks: IBM’s CICS, the Customer Information Control System, the mainframe transaction server behind a great deal of core banking.
Check yourself