cd /news/ai-products/how-i-am-building-an-ai-meeting-assi… · home topics ai-products article
[ARTICLE · art-20916] src=dev.to pub= topic=ai-products verified=true sentiment=↑ positive

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.

read3 min publishedJun 3, 2026

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 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<TranscriptionWorker> _logger;

    public TranscriptionWorker(IServiceProvider serviceProvider, ILogger<TranscriptionWorker> logger)
    {
        _serviceProvider = serviceProvider;
        _logger = logger;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        _logger.LogInformation("Transcription Background Worker started.");

        while (!stoppingToken.IsCancellationRequested)
        {
            try
            {
                // 1. Check the database for newly uploaded audio files
                using var scope = _serviceProvider.CreateScope();
                var context = scope.ServiceProvider.GetRequiredService<AppDbContext>();

                var pendingAudio = await context.AudioFiles
                    .FirstOrDefaultAsync(a => a.Status == Status.Pending, stoppingToken);

                if (pendingAudio != null)
                {
                    // 2. Hand it off to the processing service (Groq -> Gemini)
                    var processor = scope.ServiceProvider.GetRequiredService<IAudioProcessingService>();
                    await processor.ProcessAudioAsync(pendingAudio.Id);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error in TranscriptionWorker loop.");
            }

            // 3. Go to sleep for 30 seconds before checking again
            await Task.Delay(TimeSpan.FromSeconds(30), stoppingToken);
        }
    }
}

To turn it on, I just registered it in my Program.cs:

builder.Services.AddHostedService<TranscriptionWorker>();

Now, when a user uploads an audio file, my API instantly saves it to the database with a Pending status and replies to the user: "Upload successful! We'll notify you when the minutes are ready." Meanwhile, the worker silently picks it up in the background.

If you are building a .NET app that integrates with AI APIs, file processing, or heavy database tasks, stop doing it in the HTTP request pipeline. Give BackgroundService a try!

Have you used Background Services in your projects? What kind of tasks are you running in the background? Let me know in the comments below!

── more in #ai-products 4 stories · sorted by recency
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/how-i-am-building-an…] indexed:0 read:3min 2026-06-03 ·