Posts

A self-shutting-down Linux VM for a weekly batch job on Azure (.NET 8 + CZDS zone files)

I needed to process DNS zone files for about 1,000 top-level domains, load ~280 million domain names into SQL, and do it on a schedule without paying for a server that sits idle 95% of the time. This is how I set it up, what the stack looks like, and the mistakes I made along the way. The problem ICANN's Centralized Zone Data Service (CZDS) gives approved users a daily snapshot of every gTLD zone file: .biz , .info , .xyz , all the way to .com . Each file lists every registered domain in that TLD. I wanted to turn those into one table: label -> number of TLDs it is registered in , so that for a keyword like cloudapp we can show "registered in 37 TLDs". Requirements: Run once a week for now, nightly later. Big memory for the largest zones, so a real VM, not a serverless function. Cost close to zero when not running. No one logging in to press Start. The stack Layer Choice Why Worker .NET 8 console app, published self-contained for linux-x64 Str...

100k Blobs a Day and the Retention Rule Azure Doesn't Have

How a "should we just move this to SQL?" question turned into a lesson about where cloud costs actually hide. It started with a Slack message about decommissioning a web app. "How much storage is that? Curious what the pros and cons are of storing in blob vs Azure SQL?" I thought I'd answer it in five minutes. I was wrong in three separate ways, and each one taught me something. Wrong #1: "Storage is basically free" My first answer was the one everyone gives: blob storage is ~$0.02/GB/month, the data is small, cost is a rounding error. Move it to SQL, kill the web app, save the hosting bill. Then I actually looked at the write rate: ~100,000 blobs per day , one per availability check, around 20 KB each, never deleted. That changes everything: 2 GB/day → ~60 GB/month → ~730 GB/year, growing forever. Blob storage also charges per write transaction . 3 million writes/month is another $15–20, every month, regardless of retention. After one y...

Automating a Weekly Inventory Workflow with Power Automate Desktop

Every week, part of my ticket-operations workflow involved the same manual routine: open the StubHub inventory site, apply the same filters, and work down a research spreadsheet of performers one by one — searching each name, adding what qualified, and noting the ones with no events. It's exactly the kind of task that is too UI-bound for an API integration but too repetitive to keep doing by hand. So I automated it with Power Automate Desktop , Microsoft's desktop RPA tool. This post walks through how the flow works and the design decisions that made it reliable enough to run unattended, week after week. What the flow does The flow runs on a weekly cycle, and its first job is to know where it is in that cycle: Weekly reset. On start, it gets the current date and time in Pacific time and checks the day of week. If it's Sunday at 6:00 AM or later, the week is over: it resets the state file ( CompletedSpecPerformerList.txt ) and stops. Every other run continues the ...

Building a Market-Intelligence Platform for a Ticket Broker (Freelance Project)

Before my current automation work, I spent about a year as a freelancer building a market-intelligence and purchasing-workflow platform for a US ticket-brokerage client. The secondary ticket market moves fast: events go on sale at a fixed minute, prices and seat availability shift constantly across a dozen marketplaces, and the brokers who win are the ones who see changes first. My job was to give a small operations team that visibility — and to automate as much of the surrounding workflow as possible. This post is a technical retrospective of that system: what it did, how it was architected, and what I learned running data pipelines across two clouds. What the platform did At its core, the system ran four loops for the operations team: Primary-market ingest. Scheduled jobs pulled upcoming events from Ticketmaster's APIs — by state, by venue, by on-sale date — into a local SQL Server database, so the team planned their week from one screen instead of a dozen browser tabs...

Syncing Lysted → SkyBox Through Slack: When an HTML Email Is the Only API

  The final post in my series on an automation hub for a ticket-resale business. This is a very real-world integration story: a sales platform with no webhooks and no usable order API — the only thing you get is an HTML "TICKETS SOLD" notification email. Plus the settlement-reconciliation pipeline that records payments onto invoices automatically. Context The team sells tickets on Lysted, but inventory and invoices are managed centrally in SkyBox (VividSeats' POS). Every Lysted sale has to be recorded in SkyBox: matched to the right event, section, row, and seats in inventory, with the invoice reflecting the correct payout. Lysted doesn't fire webhooks. What the team did have: "tickets sold" emails already being forwarded into a Slack channel. So: Slack is the message queue, and the HTML email is the API . Pipeline 1: Recording sales Slack conversations.history (bot token) → store messages in MySQL (idempotent — nothing processed twice) → download atta...

Defending Against LLM Output: Parsing Dirty JSON in C#

  Post 3 in my series on an automation hub for a ticket-resale business. If you've ever put an LLM into a production pipeline, you know the feeling: the prompt clearly says "return ONLY valid JSON," and the model responds with... a friendly greeting, a markdown code fence, and then the JSON — occasionally missing a bracket. This post collects the techniques I use to parse LLM output safely in C#. The problem: an LLM is an "API" with no schema guarantee In my email-classification pipeline (see post 2), the model must return a list of objects like: { "uid": "452455", "subject": "Presale starts Friday!", "performer": "...", "venue": "...", "event_date": "Oct 10, 2026", "label": "PRESALES", "confidence": 0.92 } In practice the model returns every possible variation: uid is sometimes a string and sometimes a number, label i...

Featured Projects: Automation and AI Systems I Built and Run

This is a living index of the systems I'm most proud of — each one is in daily production use, and each links to a deeper technical write-up. If you're a recruiter or hiring manager, this page is the fastest way to see what I actually build. 1. AI Email-Triage Pipeline (LLM classification in production) A pipeline that classifies hundreds of ticketing emails per day (presales, releases, cancellations) using multimodal LLMs, then distributes summarized reports automatically to the relevant business departments. I fine-tuned GPT-4o-mini on a labelled dataset I built from PDF archives, put OpenAI and Gemini behind a single interchangeable JSON contract for cost/performance trade-offs, and wrote a defensive C# parsing layer — balanced-brace JSON extraction, tolerant custom JsonConverters, code-enforced business invariants — so a single malformed model response never breaks the batch. Stack: C#/.NET, OpenAI API (fine-tuning), Gemini, IMAP, SQL Server Read more: Classifying E...