How I Am Building an AI Meeting Assistant in ASP.NET Core (And Avoided Timeout Nightmares) A university student building an AI Meeting Assistant as a final-year project implemented ASP.NET Core Background Services to avoid 504 Gateway Timeout errors when processing 20-minute audio recordings. The system downloads audio from Backblaze B2, sends it to a self-hosted transcription service, and passes the text to Google Gemini for structured meeting minutes—a process taking over 90 seconds that previously caused browser timeouts when run in standard API controllers. For my 4rd-year Software Engineering final project at university, I’m building an AI Meeting Assistant. The core feature is simple: A user uploads a 20-minute audio recording of a meeting. My backend downloads it from Backblaze B2, sends it to an selfhosted transcription service to transcribe the speech, and then passes that text to Google Gemini to generate structured meeting minutes that are sent to you email. There was just one massive problem: It takes over a minute to process. If I ran this logic inside my standard API Controller, the user’s browser would just show a loading spinner for 90 seconds, eventually hitting a 504 Gateway Timeout. The solution? ASP.NET Core Background Services. Here is how I implemented a background worker to handle the heavy AI lifting, and the 3 massive "Gotchas" I ran into along the way. To understand why Background Services are necessary, think of a fast-food restaurant: The Controller The Cashier : The cashier takes your order, hands the ticket to the kitchen, and gives you a receipt. They don't cook the food. If the cashier goes to the back to grill your burger, the line of customers out the door gets angry. The BackgroundService The Kitchen Staff : The kitchen staff doesn't interact with customers. They sit in the back, continuously checking the ticket machine. When a new ticket pops up, they cook the food. In ASP.NET Core, Controllers are short-lived created and destroyed for every HTTP request . But a BackgroundService is long-lived. It is created once when the app starts, and runs continuously until the app shuts down. Building the Transcription Worker In .NET, creating a background worker is incredibly easy. You just create a class that inherits from BackgroundService and override the ExecuteAsync method. Here is the exact skeleton of the TranscriptionWorker I built for my project: public class TranscriptionWorker : BackgroundService { private readonly IServiceProvider serviceProvider; private readonly ILogger