Turning a working Acumatica customization into something you can sell is mostly not a coding exercise — it is a packaging and discipline exercise. A project that runs fine on the one tenant you built it for can still fail validation, break on a customer's next upgrade, or stall in marketplace review because of things you never had to think about while it was bespoke. This checklist is what I run through before calling an Acumatica solution ready to publish.
Package as a self-contained customization project
Everything the solution needs must travel inside the customization project — DAC extensions, graph extensions, screens, generic inquiries, reports, and any supporting DLL. Nothing should depend on a manual step someone did once on your dev box. Build the project from a clean source-controlled state, export it, then import it into a fresh tenant and confirm it publishes with no errors and no missing references. If publishing needs a SQL script or a data seed, ship those as part of the project (custom tables, database scripts) rather than as a README instruction, because instructions get skipped.
// Every added field is Usr-prefixed and lives in a cache extension,
// so a customer upgrade never collides with a future base field.
public class SOOrderExt : PXCacheExtension<PX.Objects.SO.SOOrder>
{
[PXDBString(30)]
[PXUIField(DisplayName = "Warranty Plan")]
public virtual string UsrWarrantyPlan { get; set; }
public abstract class usrWarrantyPlan : PX.Data.BQL.BqlString.Field<usrWarrantyPlan> { }
}
Run the customization validation and code review
Before you ship, use the platform's built-in Validate Customization against a target build to catch references to members that changed or were removed. Then run the ISV code-analysis / upgrade-compatibility tooling Acumatica provides for solution certification — it flags the patterns most likely to break on upgrade: direct base modifications, unpublished dependencies, deprecated API use, and DAC fields without the Usr prefix. Fix these before submission, not after a reviewer sends the package back.
On a one-off customization a missing prefix is a latent bug. In a distributed solution it is a guaranteed upgrade collision on someone else's tenant, months from now, that you will be paged for. Every custom field on a base DAC starts with Usr.
Pin a target version and plan for the next one
Decide exactly which Acumatica build your release targets and record it in the project description and your release notes — customers need to know the minimum version. Acumatica ships new major versions on a regular cadence, and a solution that compiles against one may need adjustment for the next. Keep a branch per supported major version rather than trying to make one package span all of them, and test-publish against each supported build before you claim compatibility. When a base API you rely on is deprecated, plan the migration ahead of the version that removes it, not after.
Remove single-tenant assumptions
Code that was fine on one company breaks when it lands on someone else's configuration. Audit for hard-coded IDs, branch or company references, hard-coded account or subaccount values, and assumptions about which features are enabled. Anything site-specific belongs in a setup screen or a preferences record the customer fills in, not a constant in your source. Test the solution on a tenant with multiple branches and a different chart of accounts than your dev box — that is where these assumptions surface.
Sign, license, and name the package
If your solution includes a compiled DLL, sign it and be deliberate about the assembly and namespace names so they will not clash with another vendor's package on the same tenant. Give the customization project a unique, vendor-prefixed name for the same reason — two ISVs shipping a project called Extensions is a support ticket waiting to happen. If you gate features by license level, make the enforcement fail safe and legible, so a customer without the right entitlement gets a clear message rather than a stack trace.
Documentation and marketplace submission
Package the things a reviewer and a customer both need: an install/publish guide, the target-version statement, a description of every screen and field added, and release notes. For the Acumatica marketplace / ISV program, the submission flow expects a certified package plus this documentation and a demonstration that the solution passes validation. Treat the first submission as a review conversation — reviewers will ask for the upgrade-compatibility evidence and the install steps — and keep the exact package you submitted under source control so you can reproduce it.
The pre-publish checklist
| Area | Gate before you ship |
|---|---|
| Packaging | Publishes clean on a fresh tenant with no manual steps or missing references |
| Validation | Passes Validate Customization + ISV upgrade-compatibility analysis |
| Fields | Every base-DAC field is Usr-prefixed and in a cache extension |
| Versioning | Target build stated; branch per supported major version |
| Portability | No hard-coded IDs; site-specific values in setup screens |
| Packaging identity | Signed DLL, unique vendor-prefixed project and assembly names |
| Docs | Install guide, version statement, screen/field reference, release notes |
Wrapping up
The gap between "works on my tenant" and "shippable product" is almost entirely the boring diligence above: clean packaging, passing validation, no hidden single-tenant assumptions, and a version story you can stand behind. Get those right and the marketplace review is a formality; skip them and you find out the hard way on a customer's upgrade weekend. If you are getting an Acumatica solution ready to publish, reach out or keep reading through the rest of the Acumatica blog.
Independent software engineer in Nairobi specialising in Acumatica customisations, Laravel backends, and tax fiscalisation integrations across East and Southern Africa.