The mechanics of publishing an Acumatica customization project look simple enough that people skip steps — save, hit publish, done. Most of the "why isn't my fix live" and "why did production lose a customization" tickets I get called in on trace back to exactly that: someone skipped rebuild, published from the wrong instance, or published mid-shift and clobbered a user's in-progress work. None of this is subtle once you know the sequence. It's just not written down anywhere obvious, so every team relearns it the hard way once.
The save, rebuild, publish cycle
Saving a code file inside a customization project does not rebuild the project, and rebuilding does not publish it. Those are three separate steps, and Acumatica will not do the second or third for you automatically. This is the single most common self-inflicted bug I see: a developer fixes a syntax error or a logic bug in a graph extension, saves the file, republishes — and the fix doesn't take. Nine times out of ten the project was never rebuilt after the save, so publish just redeployed the last successful build, syntax error and all (or an older, unrelated fix).
The rule that actually prevents this: after any code change, no matter how small, save it, then explicitly rebuild the project, then republish. Don't treat a one-line fix as exempt — a one-character typo fix that skips the rebuild step fails exactly the same way a large change does. If a fix "isn't working" after publish and the code looks correct, the first thing to check isn't the code, it's whether a rebuild actually happened between the save and the publish.
Always publish from Production
This is the rule that matters most on the list, because it's the one that causes damage silently. When you're managing customizations across multiple tenants on one Acumatica instance, always trigger the publish from the Production tenant, targeting all the other tenants alongside it — never publish from a non-production tenant as the source. Publishing from a stale or divergent non-prod instance doesn't just fail to update production correctly; it can actively unpublish customizations that are currently live in production, because the publish operation reconciles tenants against whatever project state the source tenant holds. If that source is behind, production goes backward.
Unpublishing from a bad source doesn't throw a dramatic error — it just leaves production running an older customization state than before you started. Nobody notices until a screen customization or a workflow a user relied on has quietly reverted. If you're promoting changes across a dev → staging → production pipeline rather than tenants on one instance, that's a related but separate discipline — see environment promotion for how the package moves between instances. The rule here is narrower and just as important: whichever tenant you publish from, on a shared instance, treat as the source of truth, and that should always be Production.
Publishing after hours, and why the lockout matters
A publish recycles the application and can modify the definition of a screen someone has open right now. If a user is mid-transaction on a screen your customization touches when publish runs, they can lose unsaved work, or land on a broken page when the site comes back. This is why publish belongs after hours, not squeezed into a quiet-looking hour mid-afternoon: "quiet-looking" and "nobody has an unsaved record open" are not the same thing.
Before publishing, disable any inbound integrations that could be mid-transaction (scheduled imports, API-driven order creation, anything that doesn't have a user watching it who can just retry), and schedule a lockout window so people aren't logging in and starting work moments before the site restarts out from under them. A short, clearly communicated lockout costs a few minutes of inconvenience; an uncommunicated publish that eats someone's half-finished AP bill costs a lot more than that in trust.
Validate after publish, before you package
Once publish completes, test the actual customization — open the screen, run the workflow, check the generic inquiry — before you go on to export the deployment package for promotion elsewhere. This ordering matters: the deployment package should represent something you've confirmed works in the environment you just published to, not just something that compiled cleanly. A clean build and a clean publish only tell you the code deployed; they don't tell you the button does what it's supposed to when a real user clicks it.
Keep the Acumatica version aligned across environments
Publishing the same customization project against different underlying Acumatica ERP versions in dev, staging, and production is a good way to get a clean publish in one place and a broken one in another, because platform APIs and DAC definitions do shift between versions. Before deploying or publishing to production, confirm dev, staging, and production are all on the same Acumatica version — update the lagging instances first rather than discovering the mismatch when a customization that worked fine in staging throws an error against production's older (or newer) build.
Wrapping up
Nothing here is exotic: rebuild after every fix because save alone doesn't recompile, always publish from Production so you're never overwriting live work from a stale source, publish after hours with integrations disabled and a lockout scheduled so nobody loses in-progress work, and test before you package rather than after. Get that sequence right and publishing an Acumatica customization stops being an event people brace for.
Independent software engineer in Nairobi specialising in Acumatica customisations, Laravel backends, and tax fiscalisation integrations across East and Southern Africa.