AppExchange

So You Want to Publish on AppExchange? Here's What Nobody Tells You.

Building a Salesforce app was 40% of the work. The other 60% was everything that comes after: namespaces, packaging, security reviews, and a lot of waiting. This is the honest guide to AppExchange publishing.

AK Haouache
17 min read
Salesforce developer at desk with AppExchange publishing process icons - security review, packaging, and approval

You've built something useful. A Salesforce app that solves a real problem. You've tested it, deployed it, used it yourself. It works.

Now you want to share it with the world. Put it on AppExchange. Let other orgs install it. Maybe even build a business around it someday.

How hard can it be?

That's what we thought when we decided to list our user access audit tool on AppExchange. We had a working product. Solid code. Good documentation. We figured the hard part was behind us.

We were wrong.

Building the product was maybe 40% of the work. The other 60% was everything that comes after: packaging, namespaces, security reviews, partner enrollment, and a lot of waiting for Salesforce to respond to anything.

This post is the guide I wish I'd found before we started. No fluff. Just what actually happens when you try to get your app onto AppExchange.


The Starting Point

The Moment You Decide to Go Public

There's a specific moment every AppExchange publisher remembers. You're looking at your app, and you think: "Other people need this too."

For us, it was a compliance automation tool. We built it internally because the manual process was painful and repetitive. When we showed it to colleagues at other companies, the reaction was always the same: "Can we have that?"

So we decided to package it up and put it on AppExchange. Simple enough, right?

Here's what we didn't know: the gap between "working app" and "AppExchange-listed product" is enormous. Not because the technical work is impossibly hard, but because nobody tells you about the process in enough detail to actually prepare for it.

Working App Code done. Tests pass. The Gap Nobody Warns You About Namespace, packaging, security review, partner enrollment, waiting, more waiting... Listed on AppExchange Available to the world.

The distance between "it works" and "it's on AppExchange" is bigger than you think.


The Real Timeline

What the Process Actually Looks Like

Every guide says "submit your app and wait for approval." Here's what that actually means, step by step, with realistic timelines based on our experience.

1
Register a Namespace
1-2 days (including the gotchas)
This was our first surprise. Your namespace gets permanently baked into every API name. We spent more time choosing it than we expected. More on this below.
2
Create a 2GP Managed Package
2-3 days
Set up the package definition, fix namespace compatibility issues, create your first package version. Some things break in ways you don't expect when a namespace gets involved.
3
Security Review Preparation
3-5 days
Run Salesforce Code Analyzer, fix findings, document your security approach. Even if your code is solid, the scanner will flag things you need to address or explain.
4
Beta Test in Clean Orgs
3-5 days
Install your package in fresh Developer Edition orgs. Things that work fine in your dev org can break in a subscriber org. Test the post-install script. Test uninstall. Test upgrades.
5
Create Partner Account & Listing
1 week
Sign up at partners.salesforce.com, accept the ISV agreement, fill out your listing details, upload screenshots. More paperwork than expected.
6
Submit for Security Review
4-6 weeks (this is where it gets slow)
You submit. Then you wait. And wait. Salesforce's security review team is thorough, but communication is... minimal. We'll talk about this.
7
Final Approval & Go Live
1-2 weeks after security review passes
If your security review passes, the listing goes through final approval. Then you're live. If it doesn't pass, fix the findings and resubmit (add another 1-2 weeks).
8-12 weeks
From "ready to submit" to "live on AppExchange"

That's right. Even if your code is perfect and your documentation is flawless, you're looking at two to three months from submission to publication. The security review alone is 4-6 weeks, and that's if you pass on the first attempt.


A person standing at a fork in the road with namespace signs - choosing a permanent namespace prefix

Choosing your namespace is a one-way door. Pick wisely.

Decision #1

The Namespace: A Decision You'll Live With Forever

This was the first thing that caught us off guard. Before you can create a managed package, you need to register a namespace prefix. And once you register it, you can never change it.

Your namespace shows up everywhere. In SOQL queries. In API calls. In your customers' Apex code. If you choose myns, every custom object becomes myns__Object_Name__c. Every field becomes myns__Field_Name__c.

Your Namespace: uaudit uaudit__ Audit_Run__c uaudit__ Finding_Type__c uaudit__ Severity__c This prefix appears in every subscriber's SOQL, Apex, and API calls. Choose wisely.
What We Wish Someone Had Told Us
  • Keep it short. Every character adds to every API name your customers will ever type. 3-6 characters is the sweet spot.
  • Register in a separate Developer Edition org. Not your Dev Hub. Not your sandbox. A dedicated DE org that exists solely to hold the namespace.
  • Wait 15-20 minutes after registration before linking it to your Dev Hub. Rush it and you'll get cryptic "invalid client ID" errors.
  • My Domain must be deployed on both the DE org and the Dev Hub before linking will work. The documentation mentions this, but it's easy to miss.
  • Allow browser popups. The linking process uses an OAuth popup. If your browser blocks it, the linking fails silently. No error message. Just nothing happens.

Person sitting in waiting room looking at phone while clock ticks and plant grows tall - the security review wait

The security review waiting room. Bring a book. Or three.

The Big Wait

The Security Review: Thorough, Confusing, and Slow

The security review is mandatory for every AppExchange listing. This makes sense. Salesforce is protecting its customers. We respect that.

What we didn't expect was the confusion around fees and the near-total silence during the review process.

The Fee Confusion

When we started researching, we found conflicting information everywhere. Some posts mentioned a $2,700 security review fee. Others said it was free for free apps. Salesforce's own documentation wasn't always clear.

Here's What We Figured Out

If your app is free on AppExchange, the security review itself costs $0. You don't pay a fee for the review.

The fee that gets mentioned online ($2,700 or similar) was historically associated with paid app listings. The policies have changed over time, which is why you find contradictory information.

Our advice: check the current Partner Program terms directly before planning your budget. Don't rely on blog posts from 2023.

The Silence

This was the hardest part. You submit your app, and then... nothing. For weeks.

No progress updates. No "we've started reviewing your app." No estimated timeline. Just a status that says "In Review" and an inbox that stays empty.

"We submitted on a Tuesday. By the following Friday, we'd heard nothing. By the end of week two, still nothing. We started wondering if our submission had disappeared into a black hole."

When feedback does arrive, it's thorough. The reviewers know what they're looking at. They'll call out specific line numbers, explain the vulnerability, and tell you exactly what to fix. The quality of the review is excellent.

It's just the communication gap between submission and feedback that's painful. If Salesforce added a simple progress indicator or weekly status email, the experience would improve dramatically.

Submit Silence (4-6 weeks) Feedback Approved The longest part of the journey is also the quietest.

Tips for Surviving the Security Review

01
Code Clean From Day One
Use with sharing on every class. Check CRUD with Schema.SObjectType before DML. Use USER_MODE and stripInaccessible() where they work, but test them in a namespaced scratch org first — they can break in 2GP managed packages.
02
Run Code Analyzer First
Salesforce provides a Code Analyzer tool with AppExchange-specific rules. Run it before you submit. Fix everything it flags or document why it's a false positive.
03
No Hardcoded Anything
No hardcoded IDs, credentials, endpoints, or even permission set names in strings. Put everything in Custom Metadata Types. Reviewers check for this.
04
Budget for Round Two
Most first-time publishers don't pass on the first submission. Plan for one round of feedback and fixes. The re-review is faster (1-2 weeks vs 4-6 weeks).

The Biggest Gotcha

The Flow Trap: Why We Rewrote Everything in Apex

This one hurt. And we didn't see it coming until we were already deep into the build.

When we started, we used Flows for core business logic. This felt like the obvious choice. Salesforce promotes Flows everywhere -- "Clicks not code." Every Trailhead module and admin guide pushes you toward declarative automation.

So we built three business processes as Flows. SLA status calculations. Remediation due dates. Audit finding rollups.

They worked beautifully in our dev org. Then we learned something that made us stop and rethink the entire architecture.

Flows are completely visible inside a managed package.

When a customer installs your managed package, they can open Setup, navigate to Flows, and read every decision node and formula you wrote. Your entire business logic is laid out in a nice visual diagram for anyone to inspect, copy, or rebuild from scratch.

Apex code? Obfuscated. Salesforce compiles your Apex into bytecode in managed packages. Customers can see class names and public method signatures, but the actual logic -- the part that makes your product unique -- is invisible. That's actual IP protection.

FLOW IN MANAGED PACKAGE Decision logic & branching rules Formulas & calculation methods Variable names & assignments Thresholds, SLA rules, state machines Complete process flow -- copyable APEX IN MANAGED PACKAGE Logic compiled & obfuscated Formulas hidden from subscribers Internal variables invisible Business rules fully protected Only class names & signatures visible Anyone can read your logic Your IP stays protected

Same business logic, completely different exposure levels. This distinction matters if your logic is what makes your product worth paying for.

But IP exposure was just the start. The deeper we dug, the worse it got.

The Five Reasons We Stopped Using Flows in Our Managed Package
  • Flows expose your intellectual property. Every decision node, formula, and variable is readable by anyone who installs your package. A competitor could open Setup, study your logic, and rebuild it without reverse-engineering a single line of code.
  • Flows can never be removed from a managed package. Once a Flow ships in any package version, it's there permanently. You can deactivate it, but you cannot delete it. Ship a bad Flow in v1.0? Congratulations, it will haunt your package metadata for the rest of its life.
  • Flows don't count toward code coverage. Salesforce requires 75% Apex code coverage for managed packages. Flow logic contributes zero to that number. If half your business logic is in Flows, you're building twice the functionality but only the Apex half counts toward your coverage threshold.
  • Flow XML destroys version control. A simple five-node Flow generates hundreds of lines of XML. Reviewing diffs in pull requests is nearly impossible. When two people touch the same Flow, merge conflicts are brutal and error-prone.
  • Testing Flows programmatically is painful. Unit testing Apex is clean and direct. Testing a Flow means either running it through the API with elaborate setup, or building test scenarios that trigger the Flow indirectly and hoping the right path executes. There's no Flow equivalent of Assert.areEqual().

What We Did About It

We converted all three Flows to Apex. SLA status calculations, remediation due date rules, audit finding counts -- all moved into @InvocableMethod service classes with full test coverage.

The conversion took two days. Two days we could have saved entirely by starting with Apex from the beginning.

The Pattern That Works: Apex for Logic, Flows for Wiring (If You Use Them at All)

If you do want Flows in your managed package, use them as thin wrappers only. The Flow handles the trigger event and calls an @InvocableMethod Apex class that contains all the actual logic. The Flow becomes a simple three-node diagram -- start, call Apex, end. Nothing proprietary is exposed.

But honestly? After going through this, our recommendation is simpler: skip Flows entirely for managed packages. Use Apex triggers, schedulable classes, and Lightning Web Components. You get proper test coverage, clean version control, and your IP stays hidden.

Save Flows for the things they're genuinely great at: letting your customers build their own automations on top of your package, using the @InvocableMethod endpoints you expose.

"Salesforce tells you to use Flows for everything. That advice stops working the moment you ship a managed package -- and nobody updates the guidance."


Two hands holding gift boxes - free green box and premium gold box with users bridging between them

Free gets your foot in the door. Premium earns its place once trust is built.

Strategy

Why We Started Free (and When We'll Go Premium)

We could have launched with a price tag. The product is solid and it solves a real problem. But we chose to launch free, and here's why.

When you're a new publisher with zero reviews and zero installs, nobody is going to pay for your app. They don't know you. They can't see testimonials. They have no reason to trust that your product will be maintained in six months.

Free removes every barrier. No procurement process. No budget approval. No risk assessment. Just install and try it.

YEAR 1 Free Build install base Collect feedback Earn reviews YEAR 2 Free + Pro Introduce paid tier Advanced features Email support YEAR 3+ Full Suite Enterprise tier API & integrations Priority support

Free first builds the trust that makes paid tiers viable later.

Why Free Works
  • Zero adoption friction for new users
  • Builds install base and social proof fast
  • AppExchange reviews come from real users
  • Feedback reveals what's actually worth paying for
  • Competitors can't undercut "free"
When Premium Makes Sense
  • After 50+ installs prove demand
  • After real users tell you what they'd pay for
  • When you have reviews and case studies
  • Gate advanced features, not core functionality
  • Offer email/phone support as a paid differentiator

The key insight: your feature toggle system is your monetization engine. If you build with Custom Metadata Type toggles from day one, separating free and paid tiers later is just a configuration change. No code rewrite needed.


The Honest Part

Things That Surprised Us

Every AppExchange journey has moments where you think "nobody mentioned this." Here are ours.

Surprise #1: Things Break When You Add a Namespace

Your code works perfectly in your dev org. Then you add a namespace prefix and suddenly certain references stop resolving. Not everything. Just enough to ruin your afternoon.

What auto-resolves (no changes needed):

Static SOQL, Apex class references, @salesforce/apex imports in LWC, custom label references, Flow references within the package. The compiler and platform handle these automatically.

What breaks (must fix manually):

Hardcoded objectApiName strings in LWC JavaScript (NavigationMixin calls), permission set names used in string comparisons in SOQL, and any dynamic references that rely on the un-prefixed API name.

Surprise #2: Your Test Framework Might Have Bugs

We ran our test suite through a regression testing tool. The results looked terrible: 18.9% pass rate across 74 tests.

After investigating every failure, we found something unexpected: none of the failures were caused by our code. They were all bugs in the testing tool itself.

The best one? An assertion type called "No Error" that was supposed to execute our code and verify it ran without errors. It never executed the code at all. It just searched for a test class matching our code string, found nothing, and reported "passed" because "no failures found." Ten of our tests passed by accident.

Lesson: Always validate your test framework independently.

A passing test only means something if the test actually ran your code. We had 111 real unit tests as our safety net, and that's what actually mattered.

Surprise #3: The ISV Portal Is... Not Intuitive

The Salesforce Partner Community portal where you manage your listing is functional but not exactly user-friendly. Finding the right page, understanding what to fill in where, and figuring out the correct order of operations took more time than we expected.

There's no guided wizard that walks you through the process. You're navigating between different sections, and the relationship between your Dev Hub, your packaging org, your namespace, and your listing isn't always obvious.

Surprise #4: Screenshots Matter More Than You Think

We initially treated screenshots as an afterthought. Just grab a few screens and upload them. But screenshots are the first thing potential users see on your listing page. They're your storefront window.

Spend time on these. Use real data (not empty screens). Annotate key features. Show the product doing something valuable, not just sitting there.


What We'd Tell You

Advice for First-Time AppExchange Publishers

01
Start the Process Early
Don't wait until your code is "perfect." The partner enrollment, namespace registration, and security review timeline add 8-12 weeks. Start them while you're still polishing features.
02
Build for Security From Day One
Every Apex class gets with sharing. Every DML gets a CRUD check first. Use bind variables in all SOQL. Do this from the first line of code, not as a retrofit. And test security patterns in a namespaced org early — some standard approaches behave differently in 2GP packages.
03
Use Feature Toggles
Custom Metadata Type toggles for every feature. This lets customers configure the app without code changes, and gives you a clean way to gate features for paid tiers later.
04
Test in Clean Orgs
Your app works in your dev org because of things you've set up over months. Install it in a fresh Developer Edition. Break things now, not after customers install.
05
Choose Your Namespace Carefully
3-6 characters. Clear meaning. Easy to type. You will live with this prefix forever. Test it in realistic API names before committing.
06
Go 2GP, Not 1GP
Second-generation packaging is Salesforce's recommended path. It integrates with source control, supports CLI-driven builds, and is where Salesforce is investing.
07
Document As You Build
Every admin guide, troubleshooting note, and configuration reference you write now saves hours later. Both for you and for your users.
08
Be Patient With Salesforce
The security review is slow. Communication is minimal. This is frustrating but normal. Plan your timeline with buffer, and don't promise launch dates until you have approval.
09
Skip Flows for Business Logic
Flows expose your IP, can never be deleted from a managed package, and don't count toward code coverage. Use Apex for all business logic. Let Flows be a customer extensibility tool, not your core engine.

Runner crossing finish line on a long track with obstacles behind them - triumphant after the AppExchange journey

The finish line exists. The track is longer than you think.

Looking Back

Was It Worth It?

Yes. Without question.

The process is longer and more complex than we expected. The waiting is frustrating. The documentation could be better. The partner portal could be more intuitive.

But we went from having an internal tool that helped one team to having a product that's available to every Salesforce org in the world. That's a fundamentally different thing.

If you have an app that solves a real problem, and you're willing to invest 8-12 weeks in the publishing process, AppExchange is worth it. Just go in with realistic expectations about the timeline, start the paperwork early, and don't be surprised when the security review takes longer than you hoped.

"Building the product was the fun part. Publishing it was the education. Both were worth doing."

Going Through This Yourself?

If you're building your first AppExchange product and want to compare notes, or if you've been through this process and have tips to share, we'd genuinely like to hear from you.

forceraft.com | Find us on the Trailblazer Community