Self-Hosted AI Code Generation Platform
for a 10,000-Person Fintech Org
Replacing expensive third-party AI coding assistants with self-hosted LLMs in a regulated fintech environment β built for data sovereignty, cost control, and production reliability, and wired directly into the Jira workflow via an autonomous agent.
Executive Summary
- What third-party AI coding tools were being replaced, and why?
- What three priorities does the solution claim to optimize for?
Executive SummaryOVERVIEWβΆ
This document presents a complete system architecture for replacing expensive third-party AI coding assistants with self-hosted Large Language Models in a regulated fintech environment. The solution prioritizes data sovereignty, cost control, and production reliability while serving 10,000 developers across multiple teams.
A regulated fintech can replace third-party AI coding tools with a self-hosted stack without giving up developer productivity β as long as sovereignty, cost, and reliability are designed in from day one, not bolted on later.
The Business Case: Why Self-Hosting Wins
- Roughly what does the current third-party API spend look like per year for 10,000 devs?
- What's the ballpark annual cost of the self-hosted alternative, and the resulting savings range?
The Cost Reality CheckFINANCEβΆ
Let me paint you a picture of what's actually happening in your organization right now:
Current State (Third-Party APIs): βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β 10,000 Developers Γ ~50 API calls/day Γ $0.03/call β β = $15,000/day = $450,000/month = $5.4M/year β β β β But wait - this is conservative. In reality: β β β’ Heavy users make 200+ calls/day β β β’ Code generation requires longer context windows β β β’ Premium models cost $0.05-0.10 per call β β β’ Real cost: $8-12M/year β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ Self-Hosted Alternative: βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β Infrastructure (Reserved Instances, 3-year commitment): β β β’ 8Γ p4d.24xlarge (A100-40GB): ~$32/hour each β β β’ Total compute: ~$256/hour = $186,880/month β β β’ Storage, networking, management: ~$50,000/month β β β’ Engineering team (3 FTE): ~$50,000/month β β Total: ~$286,880/month = $3.4M/year β β β β Annual Savings: $4.6-8.6M (54-72% reduction) β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
At 10,000-developer scale, per-call API pricing scales linearly with usage while self-hosted infrastructure scales in steps (GPU nodes) β so the larger and heavier the usage, the more self-hosting's economics win.
- Besides cost, what's the other major driver for self-hosting?
- What does code leaving the VPC expose the bank to that self-hosting avoids?
The Control ImperativeGOVERNANCEβΆ
Data Sovereignty Matrix: ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β β Third-Party API β Self-Hosted β ββββββββββββββββββββββΌββββββββββββββββββΌββββββββββββββββββββββ€ β Code leaves VPC β YES β οΈ β NO β β β Provider sees code β YES β οΈ β NO β β β Audit trail β Limited β Complete β β Model customizationβ Impossible β Full control β β Latency SLA β Provider's β Your infrastructure β β Regulatory (SOC2) β Complex β Direct control β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Cost savings alone don't justify the migration risk β the real unlock is that code never leaves the VPC, giving complete audit trails and regulatory control that a third-party API can never offer.
LLM Selection: The Evaluation War Room
- Which 8 candidate models were evaluated, and across how many dimensions?
- Which model scored highest on raw code-gen quality β and was it the one finally chosen?
The Candidate Pool8 MODELS Β· 6 DIMENSIONSβΆ
We evaluated 8 models across 6 dimensions. Here's the brutal truth:
Evaluation Matrix (Scale 1-10, higher = better): ββββββββββββββββββββββββ¬βββββββββββ¬βββββββββββ¬βββββββββββ¬βββββββββββ¬βββββββββββ β Model β Code Gen β Latency β Memory β Fine-tuneβ License β ββββββββββββββββββββββββΌβββββββββββΌβββββββββββΌβββββββββββΌβββββββββββΌβββββββββββ€ β Code Llama 34B β 8.2 β 7.5 β 8.0 β 9.0 β Open β β DeepSeek Coder 33B β 8.5 β 7.8 β 8.2 β 8.5 β Open β β Mistral 7B β 6.5 β 9.5 β 9.5 β 8.0 β Apache β β StarCoder2 15B β 7.8 β 8.0 β 8.5 β 7.5 β Open β β Llama 2 70B β 8.8 β 5.0 β 5.0 β 9.0 β Custom β β GPT-NeoX 20B β 6.0 β 7.0 β 7.0 β 7.0 β Apache β β Phi-2 (fine-tuned) β 7.2 β 9.0 β 9.8 β 6.0 β MIT β β WizardCoder 34B β 8.7 β 7.0 β 7.5 β 8.0 β Open β ββββββββββββββββββββββββ΄βββββββββββ΄βββββββββββ΄βββββββββββ΄βββββββββββ΄βββββββββββ
Benchmark scores on paper (Code Gen, Latency, Memory, Fine-tune, License) rarely tell the full story β no single model wins on every axis, which is exactly why a multi-model strategy made more sense than picking one 'best' model.
- What three-model strategy was chosen β a primary, a fast path, and a specialized path?
- Why was Llama 2 70B rejected despite strong benchmark scores?
- How did the internal 500-PR benchmark differ from public benchmarks?
The Final Decision: A Multi-Model StrategyDECISIONβΆ
WHY WE CHOSE WHAT WE CHOSE: Primary Workhorse: DeepSeek Coder 33B βββ Best code generation quality-to-latency ratio βββ Open license with no commercial restrictions βββ Excellent at understanding financial domain code patterns βββ Run on A100-40GB with comfortable headroom Fallback/Fast Path: Mistral 7B (Fine-tuned) βββ Lightning fast for simple completions βββ Can run on T4 GPUs at fraction of cost βββ Perfect for IDE autocomplete scenarios βββ 95% of simple queries don't need 33B parameters Specialized Path: WizardCoder 34B βββ Used for complex refactoring tasks βββ Better at test generation βββ Only invoked by explicit user request WHY OTHERS WERE REJECTED: Llama 2 70B: Too large, too slow βββ 2.5s inference time on A100 (unacceptable for IDE use) βββ Requires 2Γ A100s for comfortable deployment βββ Meta's custom license created legal review delays GPT-NeoX: Outdated architecture βββ RoPE embeddings missing, context handling poor βββ Community support declining StarCoder2: Good but not great βββ Filled-attention bugs in initial release βββ Finetuning documentation sparse Phi-2: Too small for complex tasks βββ Failed on multi-file refactoring βββ Cannot handle our 16K context requirements
Internal Benchmark β Did we test on OUR code? βΆ
Yes. We built an internal benchmark of 500 real PRs from the last year:
Internal Benchmark Results (Pass@1): ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β Task Category β DS-Coder β WizCoder β Mistral β ββββββββββββββββββββββββββΌβββββββββββΌβββββββββββΌββββββββββ€ β CRUD API Generation β 92% β 89% β 78% β β SQL Query Building β 88% β 85% β 82% β β Unit Test Writing β 76% β 82% β 65% β β Refactoring (Multi-file)β 71% β 74% β 42% β β Regex/Pattern Match β 94% β 91% β 88% β β Security Review β 68% β 65% β 55% β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
The best model for a task isn't always the biggest one: routing 95% of simple completions to a small fine-tuned model while reserving the 33B model for real generation work is what actually made the economics and latency work.
AWS Infrastructure: The Physical Reality
- Which AWS network layers sit in front of the wrapper service β public vs private vs GPU compute subnets?
- Where do SageMaker endpoints for DeepSeek and Mistral sit in the VPC?
Topology OverviewVPC / NETWORKβΆ
INTERNET
β
βΌ
[AWS WAF + Shield]
β
βΌ
[Route 53 DNS]ββββββ[CloudFront CDN]
β β
βΌ βΌ
ββββββββββββββββββββββββββββββββββββββ
β VPC (10.0.0.0/16) β
β β
β ββββββββββββββββββββββββββββββββ β
β β Public Subnets (DMZ) β β
β β β β
β β [Application Load Balancer] β β
β β ββββββββββββ ββββββββββββ β β
β β β ALB-1a β β ALB-1b β β β
β β ββββββββββββ ββββββββββββ β β
β ββββββββββββββββ¬ββββββββββββββββ β
β β β
β ββββββββββββββββΌββββββββββββββββ β
β β Private App Subnets β β
β β β β
β β ββββββββββββββββββββββββββ β β
β β β IDFC-Coder Wrapper β β β
β β β (ECS Fargate) β β β
β β β ββββββββ ββββββββ β β β
β β β βTask-1β βTask-2β β β β
β β β ββββββββ ββββββββ β β β
β β ββββββββββ¬ββββββββββββββββ β β
β βββββββββββββΌβββββββββββββββββββ β
β β β
β βββββββββββββΌβββββββββββββββββββ β
β β GPU Compute Subnets β β
β β β β
β β ββββββββββββββββββββββββββ β β
β β β SageMaker Endpoints β β β
β β β β β β
β β β Endpoint-1 (DS-33B): β β β
β β β ββββββββ ββββββββ β β β
β β β βml.p4dβ βml.p4dβ β β β
β β β β .24xlβ β .24xlβ β β β
β β β ββββββββ ββββββββ β β β
β β β β β β
β β β Endpoint-2 (Mistral): β β β
β β β ββββββββ ββββββββ β β β
β β β βml.g5 β βml.g5 β β β β
β β β β .12xlβ β .12xlβ β β β
β β β ββββββββ ββββββββ β β β
β β ββββββββββββββββββββββββββ β β
β ββββββββββββββββββββββββββββββββ β
β β
β ββββββββββββββββββββββββββββββββ β
β β Data/State Subnets β β
β β βββββββββββ ββββββββββββββ β β
β β βElastiCacheβ β DynamoDB β β β
β β β (Redis) β β (Cache) β β β
β β βββββββββββ ββββββββββββββ β β
β β βββββββββββ ββββββββββββββ β β
β β β SQS β β S3 Model β β β
β β β (Queues)β β Registry β β β
β β βββββββββββ ββββββββββββββ β β
β ββββββββββββββββββββββββββββββββ β
ββββββββββββββββββββββββββββββββββββββ
Isolating the wrapper service, GPU compute, and data layers into separate subnets isn't just security hygiene β it's what lets each layer scale, fail, and be audited independently.
- Between A100-40GB and H100-80GB, which was chosen and why?
- What was the target p95 latency and monthly compute budget constraint?
The GPU Math: Why This MattersCAPACITY PLANNINGβΆ
INSTANCE SELECTION DECISION TREE: Our constraints: βββ 10,000 developers, peak concurrency ~500 βββ Target latency: p95 < 800ms βββ Budget: $250K/month for compute βββ Must fit models in single GPU (no tensor parallelism) OPTION 1: A100-40GB (p4d.24xlarge) βββ 8Γ A100 GPUs, 40GB each βββ Can host 1 instance of DeepSeek-33B per GPU βββ With quantization: 2 instances per GPU βββ Per-instance cost: $32.77/hr (1-year reserved) βββ Capacity per node: 8-16 concurrent requests βββ 8 nodes Γ 8 GPUs Γ 1.5 (avg utilization) = 96 concurrent βββ COST: 8 Γ $32.77 Γ 730 = $191,380/month OPTION 2: H100-80GB (p5.48xlarge) βββ 8Γ H100 GPUs, 80GB each βββ 2-3Γ faster inference than A100 βββ Per-instance cost: $98.32/hr (1-year reserved) βββ Capacity per node: 24-32 concurrent requests βββ 3 nodes Γ 8 GPUs Γ 2 = 48 concurrent (but 2Γ faster) βββ COST: 3 Γ $98.32 Γ 730 = $215,200/month WINNER: A100s βββ Better cost/capacity ratio βββ Sufficient performance for our latency targets βββ More flexible for fine-tuning workloads
The faster, more expensive H100 wasn't the right call here β once you model real concurrency needs against latency targets, the 'better' chip can still be the worse business decision.
- What's the min/max instance range for the DeepSeek endpoint, and how does it change by time of day?
- How does the batching queue improve throughput without extra GPU memory?
Auto-Scaling ConfigurationSAGEMAKERβΆ
SAGEMAKER AUTO-SCALING POLICY: ββββββββββββββββββββββββββββββββββββββββββββββββββββββ β DeepSeek Endpoint (Primary): β β β β Target Tracking: β β βββ Metric: SageMakerVariantInvocationsPerInstanceβ β βββ Target: 8 requests per instance β β βββ Scale-out: When > 10 for 2 minutes β β βββ Scale-in: When < 3 for 10 minutes β β β β Min Instances: 4 (off-peak) β β Max Instances: 16 (peak) β β Cool-down: 300 seconds β β β β Scheduled Scaling: β β βββ Mon-Fri 8:00-10:00: Min 12 instances β β βββ Mon-Fri 10:00-17:00: Min 8 instances β β βββ Weekends/2AM-6AM: Min 2 instances β ββββββββββββββββββββββββββββββββββββββββββββββββββββββ Batch Optimization Queue: ββββββββββββββββββββββββββββββββββββββββββββββββββββββ β β β Client sends: "Write a function to..." β β β β β βΌ β β [SQS Queue accumulates for 50ms window] β β β β β βΌ β β βββββββββββββββββββββββββββββββββββββββ β β β Batch of 4 requests formed: β β β β [req1, req2, req3, req4] β β β βββββββββββββββββββββββββββββββββββββββ β β β β β βΌ β β [Single forward pass through model] β β β β β βΌ β β [Responses split and returned individually] β β β β Result: 4Γ throughput, same GPU memory β ββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Static capacity planning fails at this scale β scheduled scaling (matching known daily/weekly patterns) combined with reactive target-tracking is what kept cost and latency both in check.
The IDFC-Coder Wrapper: The Intelligence Layer
- What are the three stages a request passes through before hitting the model β auth/rate-limit, prompt engineering, caching?
- What two-tier caching strategy is used, and what's the combined hit-rate benefit?
Architecture Deep DiveWRAPPER SERVICEβΆ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β IDFC-Coder Wrapper β
β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Request Orchestrator β β
β β ββββββββββββββ ββββββββββββββ ββββββββββββββ β β
β β β Auth/ β β Rate β β Team β β β
β β β RBAC ββββ Limiter ββββ Quota Checkβ β β
β β ββββββββββββββ ββββββββββββββ ββββββββββββββ β β
β ββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββ β
β β β
β ββββββββββββββββββββββββΌββββββββββββββββββββββββββββββββ β
β β Prompt Engineering Engine β β
β β β β
β β Template: β β
β β βββββββββββββββββββββββββββββββββββββββββββββββ β β
β β β System: You are a fintech code assistant. β β β
β β β You write secure, compliant Java/Python. β β β
β β β β β β
β β β Context from codebase: β β β
β β β {injected_relevant_files} β β β
β β β β β β
β β β Jira ticket context: β β β
β β β {ticket_description_and_acceptance_criteria} β β β
β β β β β β
β β β User request: {user_prompt} β β β
β β β β β β
β β β Respond with code only, no explanations. β β β
β β βββββββββββββββββββββββββββββββββββββββββββββββ β β
β ββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββ β
β β β
β ββββββββββββββββββββββββΌββββββββββββββββββββββββββββββββ β
β β Caching Layer β β
β β β β
β β Cache Key: MD5(prompt_hash + context_hash) β β
β β β β
β β L1: ElastiCache Redis (in-memory, TTL: 1 hour) β β
β β βββ Hit rate: ~40% for repeated patterns β β
β β β β
β β L2: DynamoDB (persistent, TTL: 24 hours) β β
β β βββ Hit rate: +15% for cross-instance sharing β β
β β β β
β β Cache Invalidation: On new model version deployment β β
β ββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββ β
β β β
β ββββββββββββββββββββββββΌββββββββββββββββββββββββββββββββ β
β β Queue & Token Management β β
β β β β
β β ββββββββββββββββ ββββββββββββββββ β β
β β β Token Counterβ β Cost Tracker β β β
β β β β β β β β
β β β Input: 450 β β Team: Alpha β β β
β β β Output: 320 β β Daily: 2.3M β β β
β β β Total: 770 β β Limit: 5M β β β
β β β Est. Cost: β β Remaining: β β β
β β β $0.0008 β β 2.7M tokens β β β
β β ββββββββββββββββ ββββββββββββββββ β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Every request the wrapper handles goes through auth, quota, prompt engineering, and caching before it ever reaches the model β the 'intelligence layer' is as much about governance as it is about prompting.
- What's the effective cost per developer request after caching, and how does that compare to a commercial API?
- How are team token budgets enforced, and what happens at 80% and 100% usage?
The Token EconomyCOST MODELβΆ
This is where most self-hosted deployments fail. Let me explain why:
COST PER INFERENCE BREAKDOWN: DeepSeek Coder 33B on A100 (with batching): ββββββββββββββββββββββββββββββββββββββββββββββββββββββ β Fixed costs (per hour): β β βββ GPU instance: $32.77 β β βββ Overhead (network, storage): $2.50 β β βββ Total: $35.27/hour β β β β Throughput at batch size 4: β β βββ 400 requests per GPU per hour β β βββ Cost per request: $0.088 β β β β With caching (40% hit rate): β β βββ Effective cost: $0.053 per request β β βββ Compare to Claude API: $0.03-0.10 β β β β BUT! For our use case: β β βββ Average tokens: 800 per request β β βββ Cached requests: near-zero cost β β βββ Blended cost: $0.025 per developer request β ββββββββββββββββββββββββββββββββββββββββββββββββββββββ TOKEN BUDGETING SYSTEM: ββββββββββββββββββββββββββββββββββββββββββββββββββββββ β Team Token Allocation (Monthly): β β β β Team Alpha (Core Platform, 200 devs): β β βββ Budget: 50M tokens/month β β βββ Rate: 10K tokens/dev/day β β βββ Alerts at 80%, blocks at 100% β β β β Team Beta (Mobile, 150 devs): β β βββ Budget: 37.5M tokens/month β β βββ Rate: 10K tokens/dev/day β β βββ Can request increase via Jira ticket β β β β Enforcement via API Gateway + wrapper layer β ββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Caching isn't optional at this scale β a 40-55% effective hit rate is what turns a marginally-competitive per-request cost into a clearly winning one, and hard token budgets are what make 'no' to unlimited access defensible with data.
Jira Integration: The Autonomous Agent
- How often does the Jira agent poll, and what JQL filter does it use?
- What are the three possible output actions once the agent generates code for a ticket?
System Design β Agent Orchestration FlowEVENTBRIDGE Β· 30 MINβΆ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Jira Agent Controller β
β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Scheduler (EventBridge) β β
β β ββββββββββββββββββββββββββββββββββββββββββββββ β β
β β β Every 30 minutes: β β β
β β β cron(0/30 * * * ? *) β β β
β β β β β β
β β β βββββββββββββββ β β β
β β β β State Check β β β β
β β β β (DynamoDB) β β β β
β β β ββββββββ¬βββββββ β β β
β β β β β β β
β β β Last poll: 2024-01-15 14:00:00 UTC β β β
β β β Cursor: ticket-45678 β β β
β β ββββββββββββββββββββββββββββββββββββββββββββββ β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β β
β ββββββββββββββββββββββββΌββββββββββββββββββββββββββββ β
β β Jira Connector (Rate Limited) β β
β β β β
β β API CALL STRATEGY: β β
β β βββββββββββββββββββββββββββββββββββββββββββ β β
β β β JQL Query: β β β
β β β project = "IDFC" AND β β β
β β β status in ("In Development", "Ready") β β β
β β β AND updated >= -30m β β β
β β β ORDER BY updated DESC β β β
β β βββββββββββββββββββββββββββββββββββββββββββ β β
β β β β
β β Rate Limiting: β β
β β βββββββββββββββββββββββββββββββββββββββββββ β β
β β β β’ Jira Cloud: 10 requests/sec β β β
β β β β’ Our self-hosted: 50 requests/sec β β β
β β β β’ Token bucket algorithm: β β β
β β β - Burst: 30 β β β
β β β - Sustained: 10/sec β β β
β β β β’ Exponential backoff: 1s, 2s, 4s, 8s β β β
β β βββββββββββββββββββββββββββββββββββββββββββ β β
β ββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββ β
β β β
β ββββββββββββββββββββββββΌββββββββββββββββββββββββββββ β
β β Prompt Transformer β β
β β β β
β β Ticket β Prompt Mapping: β β
β β βββββββββββββββββββββββββββββββββββββββββββ β β
β β β { β β β
β β β "ticket_id": "IDFC-1234", β β β
β β β "title": "Add fraud detection rule", β β β
β β β "description": "...", β β β
β β β "acceptance_criteria": [ β β β
β β β "Must flag transactions > $10K", β β β
β β β "Must not exceed 100ms latency" β β β
β β β ] β β β
β β β } β β β
β β β β β β
β β β Transforms to: β β β
β β β "Write a Java method that implements..." β β β
β β βββββββββββββββββββββββββββββββββββββββββββ β β
β ββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββ β
β β β
β ββββββββββββββββββββββββΌββββββββββββββββββββββββββββ β
β β Result Publisher β β
β β β β
β β Output Actions: β β
β β βββββββββββββββββββββββββββββββββββββββββββ β β
β β β Option A: Comment on ticket β β β
β β β { β β β
β β β "body": "π€ AI Suggestion:\n```java..." β β β
β β β } β β β
β β β β β β
β β β Option B: Create subtask β β β
β β β { β β β
β β β "summary": "Implement: ...", β β β
β β β "description": "AI-generated code..." β β β
β β β } β β β
β β β β β β
β β β Option C: Create pull request β β β
β β β (via Bitbucket/GitHub API) β β β
β β βββββββββββββββββββββββββββββββββββββββββββ β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Turning Jira tickets into code isn't a single API call β it's a full pipeline of polling, rate-limited fetching, prompt transformation, and a deliberate choice of how to publish the result (comment, subtask, or PR).
- Why can't the agent trust Jira's search index alone, and what's the dual-verification fix?
- What's the fallback when the Jira rate limit is exhausted?
Handling Jira's QuirksCONSISTENCYβΆ
EVENTUAL CONSISTENCY PATTERN: ββββββββββββββββββββββββββββββββββββββββββββββββββββββ β Problem: Jira search index may be stale β β β β Solution: Dual verification β β β β ββββββββββββββββββββββββββββββββββββββββββββββ β β β 1. Get tickets from search (fast, maybe β β β β stale) β β β β 2. For each candidate, direct GET ticket β β β β (slow, always current) β β β β 3. Compare versions: β β β β if search.version < direct.version: β β β β Use direct version β β β β If already processed (idempotency key): β β β β Skip β β β ββββββββββββββββββββββββββββββββββββββββββββββ β β β β Rate Limit Exhaustion Handling: β β ββββββββββββββββββββββββββββββββββββββββββββββ β β β β’ Pre-emptive: Track X-RateLimit-Remaining β β β β β’ Reactive: Queue overflow β DLQ β β β β β’ Backpressure: Skip poll if previous not β β β β complete β β β β β’ Priority queue: Urgent tickets first β β β ββββββββββββββββββββββββββββββββββββββββββββββ β ββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Third-party SaaS APIs are eventually consistent by default β building a dual-verification (search + direct GET) pattern was necessary just to avoid acting on stale data.
Production Concerns: The Boring Stuff That Saves You
- What failure threshold trips the circuit breaker from CLOSED to OPEN?
- What's the retry backoff sequence before a request lands in the dead-letter queue?
Resilience PatternsCIRCUIT BREAKERβΆ
CIRCUIT BREAKER CONFIGURATION: ββββββββββββββββββββββββββββββββββββββββββββββββββββββ β State Machine: β β β β ββββββββββββ β β β CLOSED β (Normal operation) β β ββββββ¬ββββββ β β β β β failures >= 5 in 60s window β β β β β βΌ β β ββββββββββββ β β β OPEN β (Fail fast, return cache) β β ββββββ¬ββββββ β β β β β 30 second timeout β β β β β βΌ β β ββββββββββββ β β β HALF-OPENβ (Test with 1 request) β β ββββββ¬ββββββ β β β β β Success β CLOSED β β Failure β OPEN (back to timeout) β ββββββββββββββββββββββββββββββββββββββββββββββββββββββ RETRY STRATEGY WITH JITTER: ββββββββββββββββββββββββββββββββββββββββββββββββββββββ β Attempt 1: Immediate β β Attempt 2: 1s + random(0-200ms) β β Attempt 3: 2s + random(0-400ms) β β Attempt 4: 4s + random(0-800ms) β β Attempt 5: 8s + random(0-1600ms) [MAX] β β β β Then: Dead Letter Queue β β βββ SQS β Lambda β Alert β Slack β ββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Circuit breakers and jittered retries aren't just best practice boilerplate β they're what stands between a slow GPU endpoint and a full outage, by failing fast and falling back to cache instead of queuing forever.
- What canary traffic split is used for a new model version, and over what monitoring window?
- Name two conditions that trigger an automatic rollback.
Model Deployment StrategyCANARYβΆ
CANARY DEPLOYMENT FOR MODEL UPDATES: ββββββββββββββββββββββββββββββββββββββββββββββββββββββ β Current Model: deepseek-v1.2 (tag: prod) β β New Model: deepseek-v1.3 (tag: canary) β β β β Traffic Splitting (SageMaker): β β β β Endpoint: idfc-coder-prod β β βββ Variant-A (v1.2): 90% weight β β βββ Variant-B (v1.3): 10% weight β β β β Monitoring Period: 4 hours β β β β Automatic Rollback IF: β β βββ p95 latency > 1200ms (baseline: 800ms) β β βββ Error rate > 5% (baseline: 1%) β β βββ Token output length < 50 (hallucination risk) β β βββ User rejection rate > 20% β β β β Gradual Promotion: β β βββ Hour 4: 25% traffic β β βββ Hour 8: 50% traffic β β βββ Hour 12: 100% traffic β β βββ After 24h stable: decommission v1.2 β ββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Model updates need the same production rigor as code deploys β canary traffic splitting with automatic rollback thresholds (latency, error rate, even output length as a hallucination signal) catches regressions before they reach everyone.
- What's the split between business metrics and technical metrics on the dashboard?
- In the X-Ray trace example, which stage consumed the most time?
Observability StackCLOUDWATCH / X-RAYβΆ
MONITORING ARCHITECTURE: ββββββββββββββββββββββββββββββββββββββββββββββββββββββ β CloudWatch Dashboard β β β β ββββββββββββββββββββ ββββββββββββββββββββ β β β Business Metrics β β Technical Metrics β β β ββββββββββββββββββββ€ ββββββββββββββββββββ€ β β β β’ Requests/team β β β’ p50/p95/p99 lat β β β β β’ Tokens consumed β β β’ Queue depth β β β β β’ Cache hit rate β β β’ GPU utilization β β β β β’ Cost per team β β β’ Error rates β β β β β’ Code accepted% β β β’ Circuit breaks β β β ββββββββββββββββββββ ββββββββββββββββββββ β β β β ββββββββββββββββββββββββββββββββββββββββββββββ β β β X-Ray Tracing β β β β β β β β Trace: request-abc123 β β β β βββ API Gateway: 12ms β β β β βββ Auth check: 8ms β β β β βββ Cache lookup: 3ms [MISS] β β β β βββ SQS Queue time: 45ms β β β β βββ LLM Inference: 340ms β β β β βββ Response transform: 5ms β β β β βββ TOTAL: 413ms β β β ββββββββββββββββββββββββββββββββββββββββββββββ β ββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Business metrics (cost, adoption, code-accepted%) and technical metrics (latency, GPU utilization) have to sit on the same dashboard β otherwise engineering optimizes for speed while the business case quietly erodes.
- Soft or hard multi-tenancy β which was chosen, and what's the main cost trade-off with the other option?
- What's the biggest risk of the soft multi-tenancy model?
Multi-Tenancy IsolationSOFT vs HARDβΆ
TENANT ISOLATION MODEL: ββββββββββββββββββββββββββββββββββββββββββββββββββββββ β Option A: Soft Multi-tenancy (We chose this) β β β β β’ Shared inference endpoints β β β’ Queue-level isolation (per-team SQS queues) β β β’ Token quotas enforced at wrapper layer β β β’ Separate DynamoDB tables per team for caching β β β’ CloudWatch metrics tagged with TeamID β β β β Pros: Cost effective, simple operations β β Cons: Noisy neighbor possible β β β β Option B: Hard Multi-tenancy (Rejected) β β β β β’ Separate SageMaker endpoints per team β β β’ Full VPC isolation β β β’ Pros: True isolation β β β’ Cons: 50 teams Γ 2 GPUs = $1.6M/month minimum β ββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Soft multi-tenancy was the pragmatic choice, not the ideal one β the team consciously accepted 'noisy neighbor' risk to avoid a 10x cost blowout, while leaving a path open to harden isolation later if regulators demand it.
Iterative Challenges: The War Stories
- What was the p95 latency before optimization, and what were the main root causes?
- Which single change β batching, streaming, quantization, or ECS β do you think mattered most, and what was the final p95?
Challenge 1 β The Latency NightmareP1 INCIDENTβΆ
PHASE 1 - Unoptimized (Week 1): ββββββββββββββββββββββββββββββββββββββββββββββββββββββ β Single request flow: β β Client β API Gateway β Lambda β SageMaker β Client β β β β Results: β β βββ p50: 1200ms β β βββ p95: 3500ms β β βββ User feedback: "Slower than Copilot!" β ββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Root cause analysis β why so slow?
Why so slow? βββ No batching: One forward pass per request βββ Cold starts: Lambda initialization 200-400ms βββ No streaming: Waiting for full response βββ Model too big: 33B parameters, lots of compute βββ Network latency: Cross-AZ calls
PHASE 2 - Optimized (Week 3): ββββββββββββββββββββββββββββββββββββββββββββββββββββββ β Optimized flow: β β Client β ALB β ECS (warm) β Batched β Streaming β β β β Changes made: β β βββ Switched to ECS Fargate (no cold starts) β β βββ Dynamic batching (50ms accumulation window) β β βββ Token streaming via Server-Sent Events β β βββ Model quantization: FP32 β INT8 (2Γ speed) β β βββ KV-cache optimization for repeated prefixes β β βββ Cross-AZ placement groups for SageMaker β β β β Results: β β βββ p50: 340ms (3.5Γ improvement) β β βββ p95: 720ms (4.8Γ improvement) β β βββ Throughput: 800 req/sec (from 200) β ββββββββββββββββββββββββββββββββββββββββββββββββββββββ
The first version's 3.5s p95 wasn't a model problem β it was an architecture problem (cold starts, no batching, no streaming). Fixing the plumbing delivered a bigger win than any model swap would have.
- Why did the naive FP16 memory math not even fit on a 40GB A100?
- What three techniques finally brought memory usage under budget?
Challenge 2 β The OOM CrisisOUTAGEβΆ
What happened: Tuesday 14:00, production outage β SageMaker returning 500s. Root cause: DeepSeek-33B OOM on the 40GB A100 because the context window grew to 16K tokens.
MEMORY ANALYSIS:
ββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β GPU Memory Budget (40GB): β
β β
β Model weights (FP16): 33B Γ 2 bytes = 66GB β
β β
β Wait, that doesn't fit! β
β β
β Let's recalculate with quantization: β
β β
β Model weights (INT8): 33B Γ 1 byte = 33GB β
β KV Cache (batch_size=4, seq_len=4096): 8GB β
β Activations: 4GB β
β CUDA overhead: 2GB β
β βββββββββββββββββββββββββββββββββββββ β
β Total: 47GB β STILL DOESN'T FIT! β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββ
THE FIX:
ββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Solution 1: Flash Attention 2 β
β βββ Reduces memory by 5-10Γ for attention β
β βββ KV Cache: 8GB β 1.5GB β
β β
β Solution 2: Gradient checkpointing (even for inf) β
β βββ Activations: 4GB β 1GB β
β β
β Solution 3: Batch size reduction β
β βββ From 4 to 2 during peak β
β β
β New Memory Profile: β
β βββ Weights: 33GB β
β βββ KV Cache: 1.5GB β
β βββ Activations: 1GB β
β βββ Overhead: 2GB β
β βββ Total: 37.5GB β
FITS! β
β β
β Also: Added automatic context window adjustment β
β βββ Monitor: GPU memory utilization β
β βββ If > 85%: Reduce max_tokens by 25% β
β βββ Alert: If sustained > 90% for 5 min β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Back-of-envelope memory math (FP16 weights alone) is dangerously misleading β real GPU budgets have to account for KV cache, activations, and CUDA overhead together, and quantization plus Flash Attention were what finally made the numbers fit.
- What are the three types of hallucination encountered β think APIs, business logic, and security?
- What does the model do instead of guessing when it's unsure about a policy or API?
Challenge 3 β Hallucination MitigationQUALITYβΆ
Hallucination types encountered:
- Non-existent APIs β model invents calls like
BankAPI.getInstance().getV2Client(), an internal API not present in training data. - Incorrect business logic β model suggests a $10,000 fraud threshold when policy requires $5,000.
- Security anti-patterns β string-concatenated SQL, a firing offense in fintech code.
Solution β Grounded Prompt Engineering βΆ
Enhanced System Prompt:
You are IDFC-First Bank's internal code assistant.
CONSTRAINTS (enforced):
1. Only use APIs from our SDK:
com.idfc.banking.v3.*
com.idfc.fraud.detection.*
com.idfc.compliance.*
2. All database queries MUST use parameterized
statements (PreparedStatement only)
3. All monetary values MUST use BigDecimal,
never float/double
4. All external calls MUST have:
- Timeout (max 30s)
- Circuit breaker
- Retry with backoff
5. If you're unsure about an API or policy,
respond with: "NEEDS_CLARIFICATION: [question]"
Do not guess.
CONTEXT INJECTION:
{relevant_code_from_codebase}
{relevant_confluence_docs}
{jira_acceptance_criteria}
Post-processing Validation βΆ
Before returning to user: 1. Static Analysis (SonarQube rules): βββ No SQL injection patterns βββ No hardcoded credentials βββ Checked exceptions handled 2. API Validation: βββ Verify all method calls exist in SDK βββ If not found: replace with comment 3. Policy Check: βββ Fraud thresholds from config service βββ Inject correct values
Prompting alone can't be trusted to stop hallucinated APIs or wrong compliance thresholds β it took explicit constraints, a 'don't guess, ask' instruction, and a post-processing validation layer to make outputs safe to ship.
- What are the four adoption phases, from pioneers to laggards?
- How was the objection 'it doesn't understand our codebase' addressed?
Challenge 4 β The 10,000 User RolloutADOPTIONβΆ
PHASED ADOPTION STRATEGY: ββββββββββββββββββββββββββββββββββββββββββββββββββββββ β Phase 1: Pioneers (Month 1, 100 users) β β βββ Selected power users from Core Platform team β β βββ Direct Slack channel with platform team β β βββ Weekly feedback sessions β β βββ Goal: Iron out UX issues, gather testimonials β β β β Phase 2: Early Adopters (Month 2, 1000 users) β β βββ Add 2-3 more teams β β βββ Introduce IDE plugin (VS Code, IntelliJ) β β βββ Gamification: Leaderboard of tokens saved β β βββ Goal: Prove productivity improvement β β β β Phase 3: Majority (Month 3-4, 5000 users) β β βββ Self-service onboarding portal β β βββ Required: 30-min training video β β βββ Auto-enrollment for new hires β β βββ Goal: Make it default, not optional β β β β Phase 4: Laggards (Month 5-6, 10000 users) β β βββ Mandatory for certain ticket types β β βββ "AI-first" workflow: Must review AI suggestion β β β before writing from scratch β β βββ Goal: Complete transformation β ββββββββββββββββββββββββββββββββββββββββββββββββββββββ
ADOPTION FRICTION POINTS & SOLUTIONS: ββββββββββββββββββββββββββββββββββββββββββββββββββββββ β "It's slower than Copilot" β β β Show latency metrics, it's actually faster for β β our codebase because of context injection β β β β "The code is wrong" β β β Add "Report bad suggestion" button β β β Track rejection rate, feed back to fine-tuning β β β Public dashboard showing improvement over time β β β β "I don't trust AI" β β β Start with test generation (low risk) β β β Show examples of bugs caught by AI suggestions β β β Peer pressure: "Your team's top performer uses it"β β β β "It doesn't understand our codebase" β β β RAG pipeline: Index all repos, retrieve context β β β Fine-tune on our private code (with permissions) β ββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Technology readiness and organizational readiness are two different problems β the phased pioneer β early adopter β majority β laggard rollout mattered as much as any latency or accuracy fix.
Concrete Metrics: The Scorecard
Six-month post-launch results.
- What was the actual realized savings percentage compared to the original projection?
Cost AnalysisFINANCEβΆ
COST ANALYSIS: ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β Previous Year (Copilot Enterprise + Claude API): β β βββ GitHub Copilot: 10,000 seats Γ $39/month β β β = $4,680,000/year β β βββ Anthropic API (heavy users): $3,200,000/year β β βββ TOTAL: $7,880,000/year β β β β Self-Hosted Solution (Year 1): β β βββ Compute (A100 reserved): $2,296,560 β β βββ Storage & Networking: $300,000 β β βββ Engineering Team (4 FTE): $800,000 β β βββ Training & Onboarding: $200,000 β β βββ TOTAL: $3,596,560 β β β β SAVINGS: $4,283,440 (54.4% reduction) β β β β Year 2 Projection (with optimization): β β βββ Better batching, higher utilization: -15% compute β β βββ More caching, smaller models: -10% β β βββ Projected: $2,900,000 (63.2% savings) β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Real-world savings rarely match the initial projection exactly β tracking actuals against the original business case is what keeps the initiative honest and fundable.
- How much did p95 latency improve from the unoptimized to the optimized state?
Performance MetricsLATENCY / THROUGHPUTβΆ
Latency (DeepSeek Coder 33B, INT8): Simple completions (< 200 tokens): βββ p50: 280ms βββ p95: 620ms βββ p99: 980ms βββ SLA: p95 < 800ms β Complex generations (200-1000 tokens): βββ p50: 450ms βββ p95: 890ms βββ p99: 1400ms βββ Streaming: First token in < 100ms Throughput: βββ Peak: 1,200 requests/second βββ Average: 450 requests/second βββ Daily volume: ~15M requests βββ GPU utilization: 73% average
The multi-week latency optimization effort translated directly into a metric leadership actually cares about β this is the proof point that turns an engineering win into a business one.
- What direction did bugs-per-release and security vulnerabilities move after rollout?
Quality MetricsCORRECTNESSβΆ
Internal Benchmark (vs. Human Baseline): Code Correctness (passes tests first try): βββ Simple CRUD: 91% (human: 95%) βββ Complex business logic: 72% (human: 88%) βββ SQL queries: 88% (human: 93%) βββ Unit tests: 76% (human: 90%) Developer Acceptance Rate: βββ Month 1: 34% (rejected or heavily modified) βββ Month 3: 52% βββ Month 6: 68% βββ Target: 80% by Month 12 Time Savings: βββ Boilerplate code: 85% faster βββ API integrations: 60% faster βββ Bug fixes: 45% faster βββ Average across all tasks: 55% faster
Fewer bugs and fewer vulnerabilities post-rollout suggest the guardrails (grounded prompting, post-processing validation) were doing real work, not just adding friction.
- Roughly how did user adoption progress from Phase 1 pioneers to full rollout?
Adoption CurveGROWTHβΆ
Monthly Active Users: Month 1: 87 (87% of Phase 1) Month 2: 845 (84.5% of Phase 2) Month 3: 3,200 (64% of Phase 3 target) Month 4: 4,890 (97.8% of Phase 3 target) Month 5: 7,200 (72% of total) Month 6: 8,900 (89% of total) Daily Active Users: ~5,200 (52%) Average sessions per user: 3.4 per day Average requests per user: 47 per day Net Promoter Score: +42 (considered "Great")
Adoption doesn't happen by mandate alone β the curve reflects the deliberate phased strategy, where trust was earned with power users before it was ever required of everyone.
- What's one concrete velocity or business metric that improved post-adoption?
Business ImpactVELOCITYβΆ
Development Velocity: Story Points Completed per Sprint: βββ Before: 1,200 points (avg across teams) βββ After 3 months: 1,450 points (+20.8%) βββ After 6 months: 1,680 points (+40%) Time-to-Market: βββ Feature delivery: 22 days β 15 days (-31.8%) βββ Hot fixes: 4.2 hours β 2.1 hours (-50%) Code Quality: βββ Bugs per release: 45 β 38 (-15.6%) βββ Security vulnerabilities: 12/month β 8/month βββ Code review comments: +23% (AI catches patterns)
The ultimate test of any platform investment is whether it shows up in delivery velocity, not just in usage dashboards.
CTO's Final Thoughts
- What was the deliberate choice about which team to onboard first, and why?
What We Got RightRETROSPECTIVEβΆ
1. STARTED WITH THE HARDEST TEAM βββ Core Platform team was most demanding, most skeptical βββ If we could satisfy them, others would follow 2. BUILT FOR FAILURE βββ Every component has a fallback βββ Circuit breakers everywhere βββ "What happens when this breaks at 3 AM?" 3. MEASURED OBSESSIVELY βββ You can't improve what you don't measure βββ Every decision backed by data βββ Killed features that didn't show impact 4. TREATED IT AS PRODUCT, NOT TOOL βββ UX design, not just API βββ Developer advocacy team βββ Regular town halls for feedback
Starting with the most skeptical, most demanding team was a deliberate stress-test β if the platform could win them over, broader rollout became a much easier sell.
- What's the biggest regret around initial model size and scope?
- What GPU capacity risk should have been planned for from day one?
What We'd Do DifferentlyLESSONSβΆ
1. START SMALLER βββ Begin with 7B model for autocomplete only βββ Add complexity gradually βββ We overbuilt the initial system 2. INVEST IN FINE-TUNING EARLIER βββ Generic models hallucinate on proprietary APIs βββ Fine-tuning on our codebase would have saved months βββ Now running weekly fine-tuning jobs 3. PLAN FOR GPU SHORTAGES βββ A100 availability was constrained βββ Should have reserved instances from day 1 βββ Consider multi-cloud (GCP TPUs as backup) 4. OVER-COMMUNICATE COSTS βββ Developers don't see GPU bills βββ Should show "this request cost $0.003" βββ Creates natural conservation behavior
Overbuilding early and underestimating GPU supply constraints were the costliest mistakes β starting smaller and reserving capacity earlier would have saved months.
- Are we making developers better, or just faster β what's the concern behind that question?
- What safeguards were added to counter AI-generated 'code debt'?
The Real Question Nobody AsksREFLECTIONβΆ
We're now investing in:
- AI-generated code review tools (fighting fire with fire)
- Mandatory test coverage thresholds for AI code
- "Explain the code" sessions in PR reviews
- Tracking long-term maintenance burden of AI-generated code
The goal isn't to replace developers β it's to remove the boring parts so they can focus on architecture, security, and innovation. But we must be vigilant that we're not creating a generation of developers who can't code without AI assistance.
Speed isn't the same as skill β the team had to deliberately invest in code review discipline and maintainability tracking to make sure AI-assisted velocity didn't quietly become AI-generated technical debt.
Appendix: Key Configuration Files
- What instance type and initial instance count does the production endpoint config use?
SageMaker Deployment ConfigYAMLβΆ
# deepseek-coder-endpoint.yaml
EndpointConfigName: idfc-coder-v1-3
ProductionVariants:
- VariantName: primary
ModelName: deepseek-coder-33b-instruct-int8
InstanceType: ml.p4d.24xlarge
InitialInstanceCount: 4
InitialVariantWeight: 1.0
# Auto-scaling
AutoScalingPolicy:
TargetTrackingScalingPolicyConfiguration:
TargetValue: 8.0 # Requests per instance
ScaleInCooldown: 600
ScaleOutCooldown: 120
CustomizedMetricSpecification:
MetricName: ApproximateBacklogSizePerInstance
Namespace: AWS/SageMaker
Statistic: Average
Auto-scaling policy lives in config, not just documentation β the endpoint config is the actual source of truth for how the system behaves under load.
- What are the default vs fast model names, and what's the Redis cache TTL?
Wrapper Service ConfigurationPYTHONβΆ
# idfc_coder_config.py
class IDFCCoderConfig:
# Model selection
DEFAULT_MODEL = "deepseek-coder-33b"
FAST_MODEL = "mistral-7b-finetuned"
# Batching
MAX_BATCH_SIZE = 4
BATCHING_WINDOW_MS = 50
# Token limits
MAX_INPUT_TOKENS = 8000
MAX_OUTPUT_TOKENS = 2000
COST_PER_1K_TOKENS = 0.002 # USD
# Team quotas (monthly tokens)
TEAM_QUOTAS = {
"core-platform": 50_000_000,
"mobile": 37_500_000,
"web": 30_000_000,
"data-engineering": 25_000_000,
}
# Cache
REDIS_TTL_SECONDS = 3600 # 1 hour
DYNAMODB_TTL_HOURS = 24
# Circuit breaker
CIRCUIT_BREAKER_THRESHOLD = 5 # failures
CIRCUIT_BREAKER_TIMEOUT = 30 # seconds
# Jira
JIRA_POLL_INTERVAL_MINUTES = 30
JIRA_MAX_TICKETS_PER_POLL = 50
Team quotas, cache TTLs, and circuit-breaker thresholds are all just numbers in a config file β but they're the numbers that encode every governance and cost decision made earlier in this document.