Case Study 1: GlobalBank's Online Account Inquiry System
Background
GlobalBank's customer service representatives handle 15,000 phone calls per day. The most common request — accounting for 40% of call volume — is a simple account inquiry: "What is my balance?" or "When was my last transaction?" For years, representatives answered these questions by navigating a green-screen menu system that required 4-6 keystrokes to reach the account display.
Maria Chen's team was tasked with building a direct-access inquiry screen (transaction AINQ) that displays account information with a single keystroke after entering the account number.
Design Phase
Requirements
- Sub-second response time for account lookup
- Support for 2,000 concurrent users across 47 branches
- Display: account number, name, type, balance, status, open date, branch, last activity
- Allow rapid consecutive lookups (representative handles multiple calls)
- Accessible to all authorized customer service representatives
Design Decisions
Decision 1: Pseudo-conversational design. With 2,000 concurrent users, conversational design would require 2,000 simultaneous tasks — each holding a DB2 thread and CICS storage while the representative talked to the customer. Pseudo-conversational design meant resources were held only during the sub-second lookup, allowing CICS to serve all 2,000 users with just 50 DB2 threads.
Decision 2: Singleton SELECT instead of cursor. Since the lookup is by primary key (ACCT_NUMBER) and returns exactly one row, a direct SELECT INTO was chosen over a cursor open/fetch/close cycle. This reduces the number of DB2 calls from 3 to 1 per inquiry.
Decision 3: Minimal COMMAREA. The COMMAREA stores only a state flag (1 byte) and the last queried account number (10 bytes) — 11 bytes total. Maria kept the COMMAREA small because it is stored in CICS shared storage between interactions; with 2,000 concurrent users, COMMAREA storage adds up.
Decision 4: DATAONLY for subsequent sends. After the first ERASE display, all subsequent screen updates use DATAONLY to send only the changed data fields, reducing the data transmitted to the terminal (or terminal emulator) by approximately 70%.
Implementation Challenges
Challenge 1: The MAPFAIL Problem
During initial testing, representatives discovered that pressing Enter without typing anything caused an abend. The original code did not handle the MAPFAIL condition:
* BEFORE (bug):
EXEC CICS RECEIVE MAP('ACCTINQ') MAPSET('ACCTSET')
INTO(ACCTINQI)
END-EXEC
* If user pressed Enter with no changes, CICS raised MAPFAIL
* and the program abended
The fix was straightforward — check RESP for MAPFAIL and display a prompt:
* AFTER (fix):
EXEC CICS RECEIVE MAP('ACCTINQ') MAPSET('ACCTSET')
INTO(ACCTINQI) RESP(WS-RESP)
END-EXEC
IF WS-RESP = DFHRESP(MAPFAIL)
MOVE 'Please enter an account number' TO MSGO
PERFORM 1500-SEND-DATAONLY
EXIT PARAGRAPH
END-IF
Challenge 2: Residual Data Leakage
Representatives reported seeing account names from the previous inquiry appearing briefly when a new account number was entered. The cause: the ACCTINQO area was not initialized before populating new data. If the new account name was shorter than the previous one, trailing characters from the old name remained visible.
Challenge 3: DB2 Lock Contention
During end-of-day batch processing (5:00-6:00 PM), representatives experienced occasional "System busy" messages. The batch program was updating account balances with isolation level RS, holding locks on rows that the online inquiry was trying to read. The solution was twofold:
- Changed the inquiry's SELECT to use WITH UR (uncommitted read) since displaying a balance that is a few seconds out of date is acceptable for inquiry purposes
- Moved the batch program's start time to 10:00 PM after online traffic drops
Results
| Metric | Target | Actual |
|---|---|---|
| Response time | < 1 second | 0.12 seconds average |
| Concurrent users | 2,000 | 2,300 (tested) |
| DB2 threads needed | — | 50 (pooled) |
| Call handle time | 4 minutes avg | 2.8 minutes avg |
| Annual call savings | — | ~1.1 million shorter calls |
The inquiry screen reduced average call handle time by 30%, translating to significant operational savings.
Discussion Questions
- Why was pseudo-conversational design essential for supporting 2,000 concurrent users? Calculate the approximate storage savings compared to conversational design if each task requires 256 KB of storage.
- The team chose
WITH URfor the inquiry SELECT. Under what circumstances would this be inappropriate? What isolation level would you use for an account that displays a balance used to authorize a withdrawal? - How would you modify this design to add a "Recent Transactions" section showing the last 5 transactions below the account information?
- If GlobalBank wanted to expose this inquiry through a REST API (for a mobile app), what CICS features would you use? What changes to the COBOL program would be needed?