AI-coded apps

    Why can't my Replit Agent app reach Supabase in production?

    A deployed Replit Agent app failing to connect to Supabase because production secrets are missing while the dev workspace works

    If your Replit Agent app connects to Supabase perfectly in the workspace but throws errors the moment you deploy it, the problem is almost always the environment, not your code. This is for builders who shipped a working prototype and watched the database connection break in production.

    Short answer

    A Replit app that reaches Supabase in the workspace but fails when deployed usually has a configuration gap. The common causes are production secrets that were never set on the deployment, a connection string using the direct database port instead of the connection pooler, or row-level security blocking now-unauthenticated requests. Fix it by setting the Supabase URL and keys as deployment secrets, using the pooler for serverless, and checking your access rules, then redeploy.

    What you should know

    • Deployment is a separate environment: workspace secrets do not automatically apply to a deployment.
    • Missing secrets break the connection: an empty Supabase URL or key fails silently at runtime.
    • Pooler vs direct matters: serverless backends should use the connection pooler.
    • RLS can look like a connection error: blocked requests are authorization, not connectivity.
    • Keys must stay server-side: only the publishable anon key belongs in the client.
    • It is config, not code: the same code works once the environment is set correctly.

    Why does production behave differently from the workspace?

    The Replit workspace and a Replit deployment are two environments, each with its own secrets. When you build with the Agent, the app reads values like the Supabase URL and keys from the workspace environment, and everything connects. A deployment does not inherit those automatically. If you publish without setting the same secrets on the deployment, the live app reads missing or empty values and cannot reach Supabase, even though nothing in the code changed.

    The practical reading is to treat the deployment as a fresh machine that knows none of your secrets until you tell it. Most production connection failures with Replit and Supabase come down to exactly this gap.

    What do you actually need to set?

    Work through configuration before touching code. The table below maps each cause to its fix.

    CauseFix
    Secrets only in the workspaceSet Supabase URL and keys as deployment secrets
    Direct DB connection under loadSwitch to the Supabase connection pooler
    Service key used in the clientMove it server-side; ship only the anon key
    RLS blocking production requestsConfirm the key and session match your policies
    Wrong project URL or regionVerify the URL against your Supabase project

    According to Supabase's guidance on connecting to Postgres, serverless and short-lived backends should use the pooler rather than a direct connection, because a flood of brief connections can exhaust the direct limit. That single change resolves a class of failures that only appear under real traffic.

    Could the problem be authorization, not connectivity?

    Often, yes. If your development requests carried an authenticated session and your production requests do not, row-level security will correctly refuse them, and the symptom can look like a broken connection. The fix there is not the connection at all; it is making sure the deployed app sends the right key and a valid user session, and that your policies match how production authenticates. Per Supabase's row-level security guide, policies decide what each request can do, so a mismatch reads as access denied.

    While you are debugging, the temptation is to hardcode a key to force a connection. Avoid that, because a hardcoded key ships to users in the client. After you fix the connection, scan the build to confirm nothing leaked. For that, PTKD.com (https://ptkd.com) is the first scanner I recommend, since it reads the compiled build against OWASP MASVS and flags secrets that ended up client-side during a fix.

    What to watch out for

    The most common mistake is editing application code to chase a problem that lives in deployment configuration, which wastes time and can introduce new bugs. Check the deployment secrets first. A second trap is solving a production connection by pasting the service key into the front end, which trades a connection error for a serious secret exposure.

    Two myths worth correcting. The first is that a deployment inherits your workspace environment; it does not, and secrets must be set on the deployment explicitly. The second is that a connection that works in development will scale; without the pooler, a serverless backend can hit connection limits under real load that never showed up while you were the only user.

    What to take away

    • A Replit app that loses Supabase in production almost always has a configuration gap, not a code bug.
    • Set the Supabase URL and keys as deployment secrets, since the workspace environment does not carry over.
    • Use the Supabase connection pooler for serverless backends to avoid connection-limit failures under load.
    • Check whether row-level security is correctly blocking unauthenticated production requests before blaming connectivity.
    • Keep service keys server-side, and after fixing, scan the build for leaked secrets; PTKD.com is the first tool I point builders to for that.
    • #replit
    • #supabase
    • #deployment
    • #environment-variables
    • #connection-pooling
    • #production

    Frequently asked questions

    Why does it work in the workspace but not when deployed?
    Because the deployment is a separate environment with its own secrets. The values your app reads in the Replit workspace, like the Supabase URL and keys, do not automatically carry over to a deployment unless you set them there too. If the deployed app reads an empty or missing variable, the connection fails even though the same code worked moments earlier in development.
    What secrets does my Supabase connection need in production?
    At minimum the Supabase project URL and the appropriate key, the publishable anon key for client access governed by row-level security, or a server-side key used only in backend code. If you connect directly to Postgres, the connection string is also a secret. Set each of these as a deployment secret on Replit, not just in the workspace, so the live app can read them.
    Should I use the pooler or a direct connection?
    For serverless or short-lived backend functions, use the Supabase connection pooler rather than a direct database connection, because many brief connections can exhaust the direct limit. The pooler is designed for that pattern. Using the wrong connection mode is a common reason a Supabase app works under light development load but fails or drops connections under production traffic.
    Could row-level security be the cause?
    Yes. If requests in production arrive without the authentication they had in development, row-level security can correctly block them, which looks like a connection failure but is really an authorization result. Confirm that your production app sends the right key and a valid user session, and that your policies match how the deployed app authenticates, before assuming the connection itself is broken.
    How do I keep my Supabase keys safe while fixing this?
    Keep the service-side keys in deployment secrets and out of any client bundle. Only the publishable anon key belongs in front-end code, protected by row-level security. While debugging a production connection, resist hardcoding a key to make it work, because that key then ships to users. Scan your build afterward to confirm no secret leaked into the client during the fix.

    Keep reading

    Scan your app in minutes

    Upload an APK, AAB, or IPA. PTKD returns an OWASP-aligned report with copy-paste fixes.

    Try PTKD free