🎤 Speaking at KubeCon EU 2026 Lessons Learned Orchestrating Multi-Tenant GPUs on OpenShift AI View Session
Luca Berton
AI Engineering

AI is fast — until the database becomes the bottleneck

Luca Berton
#azure#ai#azure-functions#postgresql#key-vault#prisma#serverless#reliability#devops#platform-engineering

I can now ship features at a pace that would’ve felt ridiculous a couple of years ago.

The AI part of ProteinLens (photo → structured meal → protein estimate) is not the slow part anymore. Spec-driven “vibe coding” plus a modern cloud stack means I can go from idea to deployed endpoint in a weekend.

And then… the database showed up.

Not the database engine itself. The boring stuff around it:

This post is the story of a classic modern bottleneck: AI accelerates code, but infrastructure correctness still dominates your time-to-fix.


The setup: fast AI, production-shaped infra

ProteinLens is simple on paper:

  1. Upload a meal photo
  2. Run recognition via an AI model
  3. Store result + foods + protein numbers
  4. Show history later

The stack is what you’d expect for a clean MVP on Azure:

Everything “scales” on a slide.

Reality is that the system’s correctness depends on a chain of integrations being perfectly configured. The chain is only as strong as the dullest link.


The symptom: everything breaks at once (and it looks like your code)

It started as a normal API error:

“Failed to check email availability”

Then Prisma got more specific:

At the same time, Azure was yelling (quietly) in configreferences:

So the backend wasn’t broken because of logic.

It was broken because it didn’t have its configuration, and when it finally did, the configuration was stale or wrong.

Welcome to the part nobody screenshots for the demo.


Root cause #1: Key Vault references are permissioned and cached

The first blocker was straightforward:

Your Function App has a SystemAssigned managed identity. Your Key Vault has a policy / RBAC model. Those two must agree.

If they don’t, your app setting looks like this:

Even if the secret exists.

Fix: grant the Function App identity access to secrets

There are two valid approaches:

A) Key Vault access policies (classic model) Grant get and list for secrets to the Function App identity’s object/principal id.

B) Azure RBAC (recommended for many teams) Assign the Function App identity the Key Vault Secrets User role (or similar) at the vault scope.

Either way, the important bit is: use the Function App identity’s correct principal/object id, not “something that looks right.”


Root cause #2: “Resolved” doesn’t mean your running process updated

Here’s the trap: you fix permissions, you restart the app, you re-test… and it still fails.

You check the configreferences endpoint again and now it says:

Resolved

So why is Prisma still complaining?

Because Key Vault references resolve asynchronously, and your Function App runtime may not reload the new value until settings sync + restart actually propagates.

A practical trick is forcing an app settings update (even a dummy one) to trigger refresh.

The lesson: “Resolved” is a control-plane status. Your code runs in the data-plane. Those don’t always move in lockstep.


Root cause #3: Prisma is strict about the URL format (and it should be)

Prisma wasn’t being annoying. It was saving time.

If DATABASE_URL is missing the protocol prefix, Prisma refuses to start:

✅ correct:

postgresql://user:password@host:5432/db?sslmode=require

❌ wrong:

user:password@host:5432/db

When your Key Vault reference is denied, your app may see an empty string, or it may see the literal @Microsoft.KeyVault(...) reference instead of the resolved secret (depending on where you read it from). That’s how you end up with “URL must start with postgresql://” even though “you set it.”


Root cause #4: database password resets are slow, policy-driven, and easy to “half do”

This one hurt because it looks simple:

  1. Generate password
  2. az postgres flexible-server update --admin-password ...
  3. Update Key Vault secret
  4. Restart Function App
  5. Done

Except…

Common failure modes

The smell

If Key Vault is resolved and Prisma’s URL format is correct, but you still see:

Authentication failed … credentials are not valid

…you’re no longer debugging code. You’re debugging state.


The boring-but-effective fix checklist

When you’re in this exact situation (Key Vault + Prisma + Postgres), do this in order:

1) Verify Key Vault reference resolution

2) Force configuration refresh

3) Validate the secret content itself

Confirm the resolved value is a valid Prisma URL:

4) Reset DB password and wait for it to truly apply

5) Only then rotate Key Vault + restart the app

If you do it out of order, you create a very modern kind of chaos: everything is “configured,” nothing works.


The takeaway: AI sped up the build — but the database slowed down the truth

The AI part of ProteinLens is fast now:

But none of that matters when:

So here’s my updated mental model:

AI accelerates implementation. Databases and secrets still determine reliability.

Or, more bluntly:

The bottleneck moved from “writing code” to “making state consistent.”


What I’m adding next (so this doesn’t happen again)

A few guardrails that would’ve saved me hours:

Because the real MVP killer isn’t “AI quota exceeded.”

It’s a system that can’t reliably read its own configuration.

← Back to Blog