Case Study 35.1: API Gateway for Legacy DB2 — Modernizing Without Rewriting

Background

Meridian National Bank's core banking system runs on DB2 for z/OS with a 25-year-old COBOL application layer. The system processes 12 million transactions daily and has never missed an SLA. However, the bank is under increasing pressure to deliver mobile banking, partner APIs, and real-time data feeds — capabilities that the COBOL layer was never designed to provide.

The board has approved a modernization initiative with a firm constraint: the core DB2 system must not be rewritten or replaced. It is too stable, too critical, and too well-understood to risk a migration. Instead, the team must build a modern API layer around it.

The Challenge

Build an API gateway that: - Exposes existing DB2 stored procedures as RESTful endpoints - Serves mobile banking, partner, and internal applications - Handles 5,000 concurrent users at peak (lunch hour) - Achieves sub-500ms response times (95th percentile) - Integrates with the bank's existing RACF security infrastructure - Meets PCI-DSS and SOX compliance requirements - Can be deployed and updated without touching the core DB2 system

Architecture Decision

Option 1: Custom Java Application

Build a Spring Boot application with JDBC connections to DB2 z/OS via DB2 Connect.

Pros: Maximum flexibility, familiar technology, full control over JSON formatting. Cons: Requires ongoing development and maintenance. Must implement security mapping manually. Adds network latency (Java server to DB2 across network).

Option 2: z/OS Connect EE (Chosen for Phase 1)

Deploy z/OS Connect EE on the same z/OS LPAR as DB2, mapping stored procedures to REST endpoints.

Pros: Runs on z/OS (same LPAR as DB2, eliminating network latency). Native RACF integration. OpenAPI generation. zIIP-eligible workload reduces MPC costs. IBM-supported product with regulatory pedigree. Cons: Less flexibility in JSON transformation. Learning curve for z/OS Connect tooling. Limited to z/OS deployment.

Option 3: Hybrid (Chosen for Phase 2)

z/OS Connect for core banking operations (transfers, balance inquiries, loan payments). Spring Boot API on cloud for non-transactional operations (statement generation, analytics, notifications).

Phase 1 Implementation: z/OS Connect

Step 1: Identify Target Procedures

The team catalogued 47 stored procedures in the COBOL application and prioritized 12 for REST exposure based on mobile banking requirements:

Priority Procedure Mobile Use Case
1 PROC_GET_BALANCE Balance check
2 PROC_TRANSFER_FUNDS Account transfer
3 PROC_GET_ACCOUNT_HISTORY Transaction history
4 PROC_CUSTOMER_DASHBOARD Home screen
5 PROC_PROCESS_LOAN_PAYMENT Loan payment
6 PROC_GET_STATEMENTS Monthly statements
7 PROC_CHANGE_PIN PIN management
8 PROC_SET_ALERTS Alert preferences
9 PROC_FREEZE_ACCOUNT Card freeze
10 PROC_GET_BRANCH_INFO Branch locator
11 PROC_CHECK_DEPOSIT Mobile deposit
12 PROC_REPORT_FRAUD Fraud reporting

Step 2: Create Service and API Archives

For each procedure, the team created: 1. A service archive mapping procedure parameters to JSON fields 2. An API archive defining the REST endpoint, HTTP method, and URL path

Example for PROC_TRANSFER_FUNDS:

REST endpoint: POST /api/v1/accounts/transfers
Request body → IN parameters: fromAccount, toAccount, amount, description
OUT parameters → Response body: transactionId, statusCode, message

Step 3: Security Configuration

The security architecture layers multiple mechanisms:

  1. TLS 1.2 for transport encryption
  2. OAuth2 + JWT for mobile app authentication (issued by the bank's identity provider)
  3. API Gateway (Kong) for rate limiting, API key management, and request logging
  4. z/OS Connect maps the JWT subject claim to a RACF user ID
  5. RACF controls which user ID can EXECUTE which stored procedure
  6. DB2 authorization provides the final access control layer

Step 4: Performance Tuning

Initial performance testing showed 95th percentile response times of 800ms — above the 500ms target. Investigation revealed three bottlenecks:

  1. Connection pool exhaustion. The Liberty data source had a maximum pool size of 10. Under 5,000 concurrent users, connections backed up. Increased to 50.

  2. JSON serialization overhead. The PROC_CUSTOMER_DASHBOARD procedure returns three result sets with ~200 total rows. z/OS Connect's JSON transformation for this volume was slow. Optimized by reducing the default result set sizes (added FETCH FIRST N ROWS ONLY to the procedure's cursor declarations).

  3. zIIP utilization. The z/OS Connect Liberty JVM was configured as a general-purpose workload. Reconfigured for zIIP eligibility, moving ~70% of CPU consumption off general-purpose engines.

After optimization: 95th percentile response times dropped to 180ms.

Phase 2 Implementation: Hybrid Architecture

Cloud API Layer

A Spring Boot application deployed on Kubernetes handles: - Statement PDF generation (CPU-intensive, runs off-mainframe) - Analytics queries (runs against a DB2 LUW read replica) - Push notification management (integrates with Apple/Google push services) - Partner API management (different rate limits, API keys, and SLAs)

Event Bridge

Kafka Connect with Debezium captures changes from DB2 z/OS and publishes them to Kafka. Downstream consumers include: - Fraud detection (ML model on Kubernetes) - Real-time notification triggers - Analytics pipeline (loads to data warehouse)

Results

Metric Before (COBOL only) After (API Gateway)
Mobile banking capability None Full-featured app
Partner integrations 0 14 active partners
Average API response time (p95) N/A 180ms
Core system changes required N/A 0 (zero modifications to DB2 or COBOL)
Deployment frequency (API layer) N/A Weekly
Monthly API calls 0 85 million
Revenue from partner APIs $0 | $2.4M annually

Lessons Learned

  1. z/OS Connect dramatically reduces time to API. Creating a REST endpoint from an existing stored procedure took 2-3 days, compared to 2-3 weeks for a custom Java implementation.
  2. The hardest part was security mapping. Mapping OAuth2 tokens through API Gateway through z/OS Connect to RACF to DB2 required collaboration between four different teams.
  3. Connection pool sizing is critical. Start with the formula: pool_size = peak_concurrent_users / (1000 / avg_query_time_ms). Monitor and adjust based on actual wait times.
  4. Keep the core system unchanged. The most powerful aspect of this architecture is that DB2 and COBOL were not modified. Twenty-five years of stability were preserved while delivering modern capabilities.

Discussion Questions

  1. What would you do differently if the core system ran on Db2 for LUW instead of DB2 for z/OS?
  2. How would you handle an API request that requires data from both DB2 z/OS (transactional) and the analytics DB2 LUW instance?
  3. The partner API generates $2.4M annually. How would you design the billing system to charge partners per API call?