Deployment · environments
It works in preview and breaks in production
Or the build has been red for two days and the error means nothing to you. Both are the same category of problem: something is different between the place the code was written and the place it runs, and nobody wrote down what. Usually it is one variable, one dependency, or one function that has no secret where it is now.
Paste the full error when you write to us. Nine times out of ten it names the cause, and you will hear that before anything is agreed.
- First step
- A short call, or a written description if you would rather not talk yet
- Who you speak to
- The engineer who would do the work. No account manager, no sales call.
- Turnaround
- Most single problems are resolved within 48 hours of getting access
- Cost
- Quoted after we have seen it: scope varies, and guessing helps neither of us
How to get this fixed
Already a client? Raise it as a ticket in Golux Club and it enters the queue with an SLA attached.
Why does it work in preview but break in production?
Because the two environments differ in a way nothing declares. Usually an environment variable set in preview and not in production, a build-time value inlined at build rather than read at runtime, a dependency resolving differently on a clean install, or a case-sensitive filesystem in production that the local Mac forgave. Compare the two environments before reading the code.
The rest of this page is why that happens, how to tell which case you have, and what fixing it involves.
The usual differences
Environment variables lead: the value exists in the preview environment and not in production, or it was named with a client-visible prefix so it is inlined at build time and changing it at runtime does nothing. Edge functions come second. They run somewhere with no access to your custom secrets (API keys for Stripe, OpenAI and the like) unless those are explicitly set for them, so the function that worked locally returns 500 in production with a message it never logs. Then build-time type and import errors that the preview tolerated. Then a third-party service whose allow-list has the preview URL on it and not the real one.
How to tell it is this
- "undefined is not a function" or a missing key, only in production
- An edge function returns 500 with no useful body and nothing in the logs
- The build fails on a type error in a file nobody edited
- A feature works for you and not for users, and both are on the same version
What we do
Find the difference, close it, then make it visible next time.
- 01
Read the real error
The build log or the function log, not the message the UI shows. That is often the whole job. The cause is usually in a line nobody scrolled to.
- 02
Diff the environments
Every variable, every secret, every allow-list, preview against production. The missing one is the bug.
- 03
Fix it and deploy it
The change, the deploy, and the feature confirmed working on the live URL rather than assumed.
- 04
Make the next one loud
Error tracking wired up, so the next production-only failure sends you a message instead of waiting for a customer to complain.
What you get
- A green build and the feature working in production
- The environment difference written down, both sides
- Error tracking connected, with the first alert tested
- A short note on what to check first the next time it goes red
When this is not what you need
- Every deploy is a gamble and you have no staging. That is a practice problem; the sprint sets it up properly
- The build fails because the app has outgrown the builder. We will tell you that honestly rather than sell you a fix that lasts a week
- You want CI, tests and review gates: worth having, bigger than one fix
How it works
- 01
Tell us the symptom
One paragraph is enough. The error, the screen, what you expected. Run the free audit first if you have not; it often names the problem for you.
- 02
A call, or a written reply
Thirty minutes to look at it together, or a written answer if you prefer. Either way you find out what it is before anything is agreed.
- 03
A written offer
After the call: the scope, the approach and what we need from you. Discussed on the call, confirmed in writing.
- 04
Fixed, explained, handed back
The fix in your project, a short note on what was wrong and why, and how to check it yourself: typically inside 48 hours of getting access.
What we promise before any money changes hands
We tell you what is actually wrong, whether it is one problem or a symptom of a bigger one, and what it would take, before you commit to anything. If the honest answer is that you can fix it yourself in an afternoon, that is the answer you get, and the instructions are usually on this page already.
Questions
- I have no idea what the error means. Is that a problem?
- No. Send it as it appears. The whole thing, not a summary. Reading errors is most of what this work is.
- Can you fix it without touching production?
- We diagnose against a copy wherever possible and deploy when you approve. For a build that is already broken there is nothing to protect. The deploy is the test.
- The app worked yesterday and nothing changed.
- Something changed: a dependency published a new version, a certificate rotated, a provider changed a default, a key expired. 'Nothing changed' narrows it usefully rather than being a dead end.
- Do you fix Vercel and Netlify deploys too?
- Yes, and Supabase edge functions, Docker, and a plain server. Same process.
From the products we build
Free tools and guides from software we built and run ourselves.
- serverinspector.comThe 15 things that break an app after you ship itA launch checklist for apps with nobody on call: certificates, the domain, DNS, cold starts and the backend behind the page.Read it
- serverinspector.comIncident response playbook for small teamsRoles, a severity matrix, how often to communicate, and a checklist for the first fifteen minutes.Read it
Next step
Tell us the symptom. We will tell you if it is one problem.
We typically reply within 48 hours with what it is, whether one fix covers it, and what we need from you. If it is bigger than one problem, we say that instead, before anything is agreed.