I Spent 6 Months Building a WarcraftLogs Competitor — Solo, on AWS Serverless
Building a WarcraftLogs competitor solo on AWS serverless meant reverse-engineering an undocumented format, cutting AI costs over 95% in four rounds, and shipping a feature in 3 days because a tester asked.
By Brian Morale · Founder & Chief Architect
Updated 12 min read
In this article
After 20+ years as an enterprise architect, I spent six months of nights and weekends building a World of Warcraft combat log analysis platform with AI coaching, solo, on AWS serverless: .NET on Lambda, 41 DynamoDB tables, and AI costs cut by over 95% through four rounds of optimization. The platform is wowcoach.gg. This is how it got built, and what it cost me besides money.
How a WarcraftLogs competitor started
I've played World of Warcraft for years. If you don't play, the short version is that 20 people get together, fight a boss for 6–10 minutes, and usually die. Then they do it again, dozens of times. The game writes combat logs during these fights: massive text files with every ability cast, every damage number, every heal and every death, stamped to the millisecond. After a night of wiping, you upload your log to an analysis tool and try to work out what went wrong.
The tools I knew are built around data: charts, timelines, damage meters. Plenty of players still stare at that wall of numbers with no idea why they wiped. I wanted a platform where you could ask, in plain English, "why did we wipe?" and get a real answer. Not "do better on mechanics," but something like: "Your tank died at 3:47 because they took 340k damage in 2.1 seconds from a debuff that wasn't dispelled. Your priest had Dispel Magic available but cast Prayer of Healing instead." (For the longer version of this argument, see the death of manual log review.)
I'm a software architect by day, with the last several of those years focused on AWS serverless. How hard could it be to add some AI on top of combat logs?
Famous last words.

Getting there took six months, a custom combat log parser built from scratch, a 100x AI cost reduction, real-time collaborative features I never planned, a Texas LLC, a lost EIN, and a lawyer.
Building the parser
The plan was simple: take combat log data, pipe it to an AI, get coaching. I figured I'd use the existing analysis platform's API for the data and focus on the AI layer.
Then I started looking at the API. It had its own limits on what data I could access, rate limits, and terms of service, and it belonged to a platform I didn't control. If the API changed, or its owners decided they didn't like what I was building, I'd be dead in the water.
So I decided to build the parser myself.
A sane person would have stopped here. Blizzard's combat log format is effectively undocumented. Each line is a comma-separated event (timestamps, player IDs, ability names, damage values, coordinates), and the field layout changes between expansions, sometimes between patches. A single line looks like this:
8/18 21:47:12.841 SPELL_DAMAGE,Player-1168-0A234B,"Darkslash",0x514,
Creature-0-4232-2662-31585-214502,"Nalthor",0xa48,343293,"Sever",0x1,
4584072,5666400,0,0,3863,62613,62613,-1,1,0,0,nil,nil,nil
There are dozens of event types, each with its own field layout. Some fields are hexadecimal flags packing several boolean states. Some values that look like damage numbers are really resource states. The only way to figure it out is to generate logs, stare at them, cross-reference with in-game behavior, and iterate.
I spent weeks doing this. Weeks I could have spent building features.
Then came the accuracy chase. The incumbent tool has been parsing these logs for over a decade, with millions of uploads, and players treat its numbers as gospel. If my numbers don't match, I'm the one who looks wrong. So I'd find a discrepancy, spend hours debugging, and trace it to a difference in how we handled overkill damage, pet attribution or absorb shield accounting. Sometimes the two parsers had simply made different calls.
The breakthrough was accepting that the standard is the standard. I hit 98.99% parity and stopped chasing ghosts.
I also hit a performance milestone that made it feel worth it. I cut the parse time for a 4-hour raid file from 123 seconds to 25.9 seconds, or 132,000 lines per second, without losing that accuracy.
Parsing a 2GB file on Lambda
Here's the technical problem that made this interesting. A full raid night produces 800MB–2GB of raw text. Lambda tops out at 10GB of memory, and you need headroom for the .NET runtime and every intermediate data structure. You can't just load the file and parse it. You also can't truncate, because players expect analysis of their entire session.
The answer is a two-pass streaming architecture.
Pass 1: boundary detection. Stream the entire file line by line from S3 without storing content, and only detect boundaries: zone changes, dungeon starts, boss encounter starts and ends. The output is a list of byte offset ranges, one per encounter. Memory footprint is about 100KB regardless of file size.
Pass 2: run-by-run processing. For each boundary, use S3 range requests to fetch only that encounter's bytes. Parse it fight by fight. After each fight, convert to Parquet, write to S3, release the memory, and move on.
That turns a 2GB memory problem into a series of 50–200MB problems, each processed and discarded before the next one starts. When metadata grows past 2.5GB of heap, which happens on 100+ fight raid nights, fight data spills to Lambda's 10GB ephemeral disk as compressed files and is reloaded on demand.
The result: 2GB files parse reliably in a single Lambda invocation in under 30 seconds. No servers, no containers, no orchestration. One function.
The $0.20 problem
With the parser working, I wired up the AI coaching layer. The first version was straightforward: stuff all the fight data into a prompt, add the user's question, send it to Claude Sonnet on AWS Bedrock, and return the response.
It worked, and the coaching was genuinely good: specific, timestamped and actionable. The AI would trace a chain of events (the first death caused a healing gap, which caused a second death, which snowballed into a wipe) and explain it in a way that made sense.
Then I looked at the bill.
At $3.00/M input tokens and $15.00/M output tokens, each query cost $0.10–0.20. A user asking 10–50 questions in a session meant $1–10 in AI costs per user per night. For a product I planned to sell at $5.99–12.99/month, the math was impossible.
I needed costs down by at least 10x. I ended up cutting them by over 95%. It took four separate rounds of optimization, and the first one was embarrassing.
The logs I should have checked
I'd enabled prompt caching, which should have cut costs sharply for repeated content. Weeks went by before I checked the token usage logs and saw Input: 1727 (cache: 0).
Zero cache hits. For weeks.
The problem was prompt structure. I had dynamic content (the user's question, combat data) mixed in with static content (system prompt, tool definitions). Prompt caching needs the cacheable content to be a contiguous prefix: everything static at the top, everything dynamic at the bottom. I'd been re-processing the whole system prompt on every request.
The fix took 20 minutes. Checking the logs on day one would have saved weeks of wasted money.
The provider switch
Next came the big lever. Gemini 2.5 Flash launched at $0.15/M input and $0.60/M output, roughly 20x cheaper than Claude Sonnet on Bedrock. For my use case, reading structured data and writing coaching responses, the quality was comparable.
Because I'd built a provider-agnostic interface from the start (a shared abstraction for chat completion with tool use), switching the primary provider was an environment variable change, not a rewrite. I kept Claude on Bedrock as a fallback.
Pricing wasn't even the main reason I switched. Rate limits were.
AWS Bedrock started me at 2 requests per minute. Two, for a product where a single user session might generate 10–20 AI queries. I filed a quota increase request and waited. It took a month to get approved for 200 requests per minute: better, but still not enough for production with concurrent users.
Anthropic's direct API capped me at 50 requests per minute, with no clear path to more.
Gemini gave me 1,000 requests per minute out of the box. No phone calls, no quota requests, no waiting. When you're a solo developer with no enterprise sales relationship, default rate limits decide which providers you can realistically build on. That never shows up in a pricing calculator, and it nearly killed the project before costs did.
Tools instead of monolithic prompts
The real fix was moving from monolithic prompts to a tool-based architecture.
Dumping all the fight data into context and letting the AI sort it out was wasteful. A monolithic prompt for a complex fight could run 40–100k tokens, and most of them had nothing to do with what the user asked.
The tool-based design flipped that. The AI starts with minimal context and decides what it needs. It sees 25+ available tools (get_death_recap, get_ability_usage, get_mechanic_failures, get_player_performance) and picks 2–4 relevant ones per question.
"Why did I die?" fetches the death recap. "Why did we wipe?" starts with get_death_recap, finds that the first death was the tank, then calls get_mechanic_failures to check whether a swap was missed. The AI reasons through it step by step, pulling data as it goes.
Token usage dropped 70–85%. And because the AI only sees relevant data, accuracy improved. Less noise, better answers.
A typical coaching conversation now costs over 95% less than the first implementation. The fourth round targeted AI thinking tokens, tuning reasoning depth per feature so the model doesn't overthink structured tasks. That's the difference between a product that bleeds money and one that works.
The feature I didn't plan to build
The original vision was upload a log, get AI coaching. Then real users showed up.
One of my early alpha testers, a well-known figure in the WoW tools community, spent three hours exploring the platform on his first visit. He gave specific feedback, pointed out edge cases and suggested improvements. Then he asked for something I hadn't considered: an instant fight replay.
After a wipe, the raid leader could replay exactly what happened, with every player's position and every mob animated on the actual game map, and draw on it in real time: annotations, arrows, circles. Miro for raid strategy, on top of real fight data, shareable by link, with the replay and drawings updating live for everyone connected.
It was not a small ask. It was the right one.
That's how raid leaders actually work during progression. They wipe, they need to figure out what went wrong, and they need to explain positioning changes to 20 people over Discord, usually with verbal descriptions and crude drawings.
So I built it. The fight replay pulls position data from the parsed combat log, transforms coordinates to map space, and animates them on a canvas. The collaborative drawing layer runs on WebSockets, so every connected viewer sees the same playback state and each other's annotations in real time. A raid leader can pause at the moment of a wipe, draw "don't stand here" arrows, and 20 people see them instantly.
It shipped in three days.
That feature, along with automatic wipe analysis that runs between pulls and posts results to Discord, changed what WowCoach is. It stopped being a tool you check after raid night and became one you use during raid night. The desktop companion app detects when a fight ends, uploads the log, triggers the parse, runs the AI analysis, and pushes the wipe summary to the raid's Discord channel, all automatically. The raid leader sees what went wrong before the next pull timer expires. (Curious what the AI side actually says? Meet Coach Clutch.)
I didn't plan any of this. I built what users told me they needed for Mythic progression. And it turns out that shipping a complex real-time feature in days instead of months is the only competitive advantage a solo developer has.
Building with Claude Code
That speed comes from somewhere. This project wouldn't exist at its current scope without AI-assisted development, specifically Claude Code, Anthropic's terminal-based coding agent.
Claude Code reads your codebase, understands your architecture, and makes changes across multiple files. I describe a feature ("add a WebSocket endpoint that broadcasts fight replay state to connected viewers, with collaborative drawing events") and it plans the implementation across CloudFormation templates, .NET backend services and the Next.js frontend.
The effect compounds. By month three it knew my naming conventions, my CloudFormation patterns and my repository structure. It stopped writing generic code and started writing my code.
It struggled too. It hallucinated combat log field layouts (undocumented formats aren't in anyone's training data), proposed architectures that wouldn't survive Lambda's constraints, and sometimes "improved" working code with needless abstractions. The fix was always to be specific about constraints: "This runs on Lambda with a 15-minute timeout and 10GB memory. The file streams from S3 using range requests. Don't load it into memory." Constraints get better AI output than open-ended asks.
Six months of nights and weekends produced 8 Lambda functions, 41 DynamoDB tables, a Next.js frontend, a Tauri desktop app, real-time collaborative features and a CI/CD pipeline. They also produced a Texas LLC, an EIN I had to chase down from the IRS during a partial government shutdown, a payment processor that needed a hand-signed ownership structure document for a single-member LLC, and a code signing certificate that nearly broke me.
That last one deserves its own paragraph. To ship a Windows desktop app without terrifying "Unknown Publisher" warnings, you need a code signing certificate, and to get one under your business name, the certificate authority has to verify that your LLC exists. Mine was two months old. Azure's identity verification rejected my Texas driver's license outright, with no workaround. I moved to a third-party CA, which needed my phone number listed in an approved business directory. D&B gave me system errors. ZoomInfo turned out to be enterprise sales software. My LLC was too new to appear anywhere. I ended up hiring a lawyer to write a legal opinion letter confirming that WowCoach LLC is a real company and I'm its real owner. A lawyer, to sign a desktop app.
Nobody warns you about that part. The code is the fun part. The business infrastructure is the grind.
What I learned
Check your AI logs on day one. I ran for weeks with zero prompt cache hits because of a structural mistake, which is money on fire.
Stop chasing the last 1%. I spent weeks matching the incumbent's numbers exactly, debugging edge cases where our two parsers had simply made different calls. Ship at 99% and move on.
Let the AI fetch instead of force-feeding it. Tool-based architectures beat monolithic prompts on cost, accuracy and extensibility. If you're stuffing everything into context, stop.
Build the provider abstraction early. When Gemini Flash dropped and cut my costs 20x, I migrated in a day. Locked to one provider's SDK, that would have taken a month.
Ship fast and listen. The features that matter most (real-time wipe analysis, collaborative replay, Discord integration) weren't in my original plan. They came from watching how people actually use the tool.
The question I still can't answer
I can tell you the parser is accurate, the AI costs are sustainable and the architecture scales. What I can't tell you is whether people will pay for it.
The incumbent tool is free for most players. It has a decade of trust, millions of users and deep roots in the community. I'm charging a monthly subscription for something that overlaps with what players already have, and betting that AI coaching, real-time wipe analysis and collaborative strategy tools are different enough to justify it. (For the honest side-by-side, see WarcraftLogs vs WoWAnalyzer vs WowCoach.)
Some nights I'm convinced they are. The AI gives answers that take experienced players 20 minutes of manual log reading to find, and the real-time features cover a part of raid night I hadn't seen tooling built for. Other nights I stare at the pricing page and wonder whether players will try it once, think "cool," and go back to what they know.
I don't have an answer yet. But AI doesn't have to be expensive. The hardest part is the same as it's always been: building something people actually want to use.
Brian Morale is Founder & Chief Architect of WowCoach.gg. With 20+ years in enterprise software architecture, he builds systems that scale — whether it's financial platforms by day or AI coaching engines by night.
See what your logs actually say.
Upload a combat log and Coach Clutch explains — in plain English — what went wrong and how to fix it. No spreadsheet archaeology required.
Free with Battle.net sign-in · no card
Written by
Brian Morale
Founder & Chief Architect
Related topics

