AEM Hubv1.0
General•15 min read•Oct 4, 2026

Run Modes in AEM: Context-Aware Configuration

#Run Modes#Ports

Introduction

Every AEM instance needs to behave differently depending on where and how it's running — an author instance shouldn't expose the same things a publish instance does, a dev environment shouldn't use production credentials, and a US-region instance might need different configuration than an EU-region instance. AEM solves this with Run Modes: labels attached to an instance at startup that determine which OSGi configurations, content, and behaviors get activated. Understanding run modes is foundational — nearly every real AEM project uses them to manage environment-specific configuration (database URLs, API keys, replication agents, cache settings) without maintaining separate codebases. After reading this article, you'll understand the built-in run modes AEM ships with, how to define your own custom run modes, the critical rule of mutual exclusion that governs install-time run modes, and how run modes map to the ports you learned about when installing AEM locally. Prerequisites: Familiarity with installing AEM locally (see Installing AEM Server Locally.md) and basic OSGi/config folder structure concepts.


What Is a Run Mode?

A run mode is simply a string label assigned to a running AEM instance. When AEM starts, it checks which run modes are active and uses that information to decide:

  1. Which OSGi configurations to apply (via config.<runmode> folders)

  2. Which content packages to install

  3. Which bundles to start or skip

  4. How certain core features behave (e.g., whether the Replication/Package install UI is restricted)

Run modes are evaluated against your repository's /apps and /libs structure through a naming convention: any folder suffixed with .<runmode> only applies when that run mode is active.

Java
config/                          ← Applies to ALL instances
config.author/                   ← Applies only when "author" run mode is active
config.publish/                  ← Applies only when "publish" run mode is active
config.author.dev/               ← Applies only when BOTH "author" AND "dev" are active

That last example is important — multiple run modes can be combined, and a folder with multiple dot-separated run modes requires all of them to be active simultaneously for its configs to apply.

How Run Modes Are Set

Run modes are specified at JVM startup using the -r flag (as you saw in the local installation article):

Bash / CLI
java -jar aem-author-p4502.jar -r author,dev,local

This instance now has three run modes active simultaneously: author, dev, and local. AEM merges configurations from config/, config.author/, config.dev/, config.local/, and any combined folders like config.author.dev/ — all at once.

You can also append run modes after the instance has already been created by editing the crx-quickstart/bin/start script, or by checking/setting them via the Web Console at /system/console/vmstat or /system/console/configMgr (though the cleanest approach is always to set them at startup).


Pre-Built (Out-of-the-Box) Run Modes

AEM ships with a set of run modes that are either automatically assigned or part of its standard vocabulary. These fall into a few categories.

1. Installation-Time Run Modes: author and publish

These are the two most fundamental run modes in all of AEM, and they're mutually exclusive (more on that below). You choose one at install time:

  • author — Marks the instance as a content-authoring environment. Enables the authoring UI, CRXDE Lite, component dialogs, workflow consoles, and replication agents that push content out to publish instances

  • publish — Marks the instance as a content-delivery environment. Strips out authoring tooling by default, optimizes for read performance, and is the target that end-users/visitors actually hit (usually behind a Dispatcher)

Bash / CLI
# Author instance
java -jar aem-author-p4502.jar -r author

# Publish instance
java -jar aem-publish-p4503.jar -r publish

2. Default Port-Associated Behavior

While ports themselves aren't run modes, there's a long-standing convention tightly linking run mode to port number:

Run Mode

Default Port

Purpose

author

4502

Authoring environment

publish

4503

Delivery environment

Additional author instances (clustering)

4512, 4522...

Scaled authoring tier

Additional publish instances (clustering/farm)

4513, 4523...

Scaled delivery tier (load-balanced)

The port is set independently via the -p flag — AEM doesn't force a port based on run mode — but every real-world project follows this convention so anyone on the team can immediately tell what an instance is just from its port number.

Bash / CLI
java -jar aem-author-p4502.jar -r author -p 4502
java -jar aem-publish-p4503.jar -r publish -p 4503

3. Environment/Topology Run Modes (Industry Convention, Not Enforced by Code)

AEM doesn't ship these as hardcoded values, but Adobe's own documentation and virtually every enterprise project uses this standard set for environment separation:

  • dev — Developer's local or shared dev environment

  • stage (or staging/uat) — Pre-production, used for QA/UAT

  • prod — Production/live environment

These are passed alongside author/publish:

Bash / CLI
java -jar aem-author-p4502.jar -r author,dev
java -jar aem-publish-p4503.jar -r publish,prod

4. Automatically Assigned Run Modes

Beyond what you pass with -r, AEM automatically computes and adds certain run modes at startup that you don't control directly:

  • samplecontent — Active if sample content (like the We.Retail or WKND demo site) was installed. Absence of this run mode on a "nosamplecontent" quickstart avoids installing demo content at all

  • Cluster-related modes — When TarMK clustering or certain Oak configurations are in play, additional internal modes may be present

  • nosamplecontent — Some quickstart jar variants are literally named/configured to skip sample content installation entirely, which is standard for anything beyond a pure learning sandbox

5. Adobe-Reserved Namespaces

Adobe reserves a few run mode "families" for its own internal use that you should never try to repurpose for custom meanings:

  • Run modes starting with internal product prefixes used by AEM Forms, Communities, Screens, or Assets add-ons when those are installed (e.g., specific modes activated automatically when the Forms add-on package is present)


Custom Run Modes

Beyond the built-in vocabulary, you can — and in real projects, must — define your own run modes to represent anything specific to your business or infrastructure.

Common Custom Run Mode Examples

Bash / CLI
# Geographic/regional run modes
java -jar aem-publish-p4503.jar -r publish,prod,us

# Brand-specific run modes (multi-brand AEM setup)
java -jar aem-publish-p4503.jar -r publish,prod,brandA

# Combined region + environment
java -jar aem-publish-p4513.jar -r publish,stage,eu

This enables configuration folders like:

Java
config.publish.prod.us/
  └── com.example.PaymentGatewayConfig.config   ← US payment gateway settings

config.publish.prod.eu/
  └── com.example.PaymentGatewayConfig.config   ← EU payment gateway settings (GDPR-compliant endpoint)

Both configs target the exact same OSGi service (PaymentGatewayConfig), but only one activates depending on which combined run mode set is active on that particular instance — no code branching required.

Defining Custom Run Modes at Startup

Custom run modes are passed exactly like built-in ones via -r, comma-separated, no special registration needed:

Bash / CLI
java -Xmx4096m -jar aem-publish-p4503.jar -r publish,prod,us,brandA

Defining Custom Run Modes Dynamically (Install-Time vs. Runtime)

There are actually two categories of run modes in AEM, and this distinction matters a lot:

1. Install-Time Run Modes (also called "fixed" run modes)

  • Set once via -r at the very first startup (or via sling.run.modes in sling.properties)

  • Written into crx-quickstart/launchpad/sling.properties as the sling.run.modes.install property

  • Cannot be changed after the instance is first provisioned without wiping/reinstalling — this is intentional, since things like author/publish fundamentally shape the repository structure and shouldn't change mid-life

2. Runtime-Changeable Run Modes

  • Some run modes (particularly custom ones you add later, or ones not in the original fixed set) can be appended dynamically by editing sling.properties directly, or occasionally through JVM system properties on restart, without a full reinstall

  • Less common in practice — most teams decide all their run modes up front and bake them into each environment's startup script

For nearly all practical purposes: decide your full run mode list before first startup, especially author vs. publish, since changing it later is disruptive.

Where Custom Run Mode Values Live

The actual active run mode set for a running instance is stored in:

Java
crx-quickstart/launchpad/sling.properties
Java
sling.run.modes=author,dev,us,brandA
sling.run.modes.install=author,dev,us,brandA

You can verify active run modes on a running instance via the Web Console:

Java
http://localhost:4502/system/console/vmstat

Look for the "Active Sling Settings" section, which lists the exact run mode set currently in effect.


Mutual Exclusion: The Critical Rule

This is the single most important constraint to understand about run modes, and it trips up nearly every AEM beginner at least once.

The Rule

author and publish are mutually exclusive. An AEM instance must be started with exactly one of them — never both, never neither (in practice, you always need one or the other for a functioning instance).

Bash / CLI
# ❌ INVALID — will cause unpredictable behavior / conflicting configs
java -jar aem-p4502.jar -r author,publish

# ✅ VALID
java -jar aem-author-p4502.jar -r author

# ✅ VALID
java -jar aem-publish-p4503.jar -r publish

Why This Matters

Author and publish run modes drive fundamentally incompatible configurations:

Behavior

Author Config

Publish Config

CRXDE Lite access

Enabled

Disabled

Component authoring dialogs

Active

Not needed (read-only rendering)

Replication agents

"Publish" agents configured (push content OUT)

"Reverse replication" / flush agents configured (push activity logs back)

User-facing authentication

Author-only users

Public/anonymous access patterns

Workflow launchers

Full workflow console active

Typically disabled or minimal

Default ACLs (access control)

Author group permissions

Anonymous/public read permissions

If both run modes were active simultaneously, AEM would try to apply both sets of OSGi configurations at once, producing conflicting replication agent setups, broken security postures (e.g., accidentally exposing author-only functionality publicly), and generally undefined behavior. AEM doesn't gracefully "merge" these — it's an architectural assumption baked throughout the product that an instance is one or the other.

Mutual Exclusion Beyond Author/Publish

While author/publish is the textbook example, the same principle of "pick one, not both" commonly applies to any run modes representing mutually incompatible deployment contexts you define yourself — for example:

Bash / CLI
# ❌ Conceptually invalid — an instance can't simultaneously be
# both a US-only deployment and EU-only deployment if those
# imply different compliance/data-residency configs
java -jar aem-publish-p4503.jar -r publish,prod,us,eu

AEM itself won't stop you from doing this (unlike author+publish, which causes clear structural problems) — but it will silently merge configuration from both config.publish.prod.us/ and config.publish.prod.eu/, which is almost certainly not what you want. This is why good run mode design treats certain custom run mode groups (region, brand, tenant) as logically mutually exclusive even though AEM doesn't technically enforce it at the framework level the way it does with author/publish.

Combinable (Non-Exclusive) Run Modes

In contrast, most other run modes are designed to be combined freely:

Bash / CLI
# These all coexist without conflict
java -jar aem-author-p4502.jar -r author,dev,local,debug

dev, stage, prod (environment tier) typically combine cleanly with author/publish (instance type) and with custom modes like region or brand — that's the entire point of the system: layering independent, combinable dimensions of configuration (instance type × environment × region × brand) without writing conditional code.


Run Modes and Ports: How They Relate

Run modes and ports are independent settings — one does not cause the other — but in practice they're always used together to build a coherent multi-instance local or clustered setup. Revisiting the installation conventions:

Bash / CLI
# Author on its conventional port
java -jar aem-author-p4502.jar -r author,dev -p 4502

# Publish on its conventional port
java -jar aem-publish-p4503.jar -r publish,dev -p 4503

Why Pairing Matters in Practice

  1. Local development: You typically run one author (4502) and one publish (4503) instance side-by-side to test the full author → activate → publish flow

  2. Clustering: When scaling publish horizontally, each additional publish instance gets both the publish run mode and a new port:

    Bash / CLI
    java -jar aem-publish-p4503.jar -r publish,prod -p 4503
    java -jar aem-publish2-p4513.jar -r publish,prod -p 4513
    java -jar aem-publish3-p4523.jar -r publish,prod -p 4523

    All three share the publish run mode (and therefore identical OSGi config), but run on different ports and are typically load-balanced behind a Dispatcher/reverse proxy

  3. Multi-region or multi-brand farms: Combine run mode layering with port separation so each instance is both logically configured correctly (via run mode) and network-addressable distinctly (via port):

    Bash / CLI
    java -jar aem-publish-us-p4503.jar -r publish,prod,us -p 4503
    java -jar aem-publish-eu-p4513.jar -r publish,prod,eu -p 4513

Port Does NOT Determine Run Mode

A common beginner misconception: thinking that running on port 4502 makes an instance an author instance. It does not. Port is purely a network binding; run mode is purely a configuration/behavior switch. You could, in theory, run a publish-run-mode instance on port 4502 — it would work, it would just break every convention your team relies on to quickly identify instances. Always set both explicitly and keep them aligned with convention.


Practical Example: Multi-Environment Configuration with Run Modes

Imagine a project with this OSGi config structure for a database connection service:

Java
ui.config/src/main/content/jcr_root/apps/myproject/osgiconfig/
├── config/
│   └── com.example.DatabaseService.config          ← Fallback (rarely used directly)
├── config.author.dev/
│   └── com.example.DatabaseService.config          ← Points to local dev DB
├── config.author.stage/
│   └── com.example.DatabaseService.config          ← Points to staging DB
├── config.publish.prod/
│   └── com.example.DatabaseService.config          ← Points to production DB (publish-safe, read replica)
└── config.author.prod/
    └── com.example.DatabaseService.config          ← Points to production DB (author, read-write)

When you deploy the exact same code package to four different instances started with different run modes, each one automatically picks up the right database connection — no manual reconfiguration, no environment-specific code branches, no risk of a developer accidentally pointing a dev instance at production data because the correct config is baked into the run mode structure itself.

Bash / CLI
# Dev author — picks up config.author.dev
java -jar aem-author.jar -r author,dev -p 4502

# Staging author — picks up config.author.stage
java -jar aem-author.jar -r author,stage -p 4502

# Production author — picks up config.author.prod
java -jar aem-author.jar -r author,prod -p 4502

# Production publish — picks up config.publish.prod
java -jar aem-publish.jar -r publish,prod -p 4503

Common Pitfalls

Pitfall 1: Setting Both author and publish

The Mistake: Copy-pasting a startup script and forgetting to remove one run mode, ending up with -r author,publish.

Why It Happens: Usually a leftover from testing or a careless script template.

Fix: Always explicitly audit your startup scripts per environment; consider a sanity-check step in deployment automation that fails the build if both appear together.

Pitfall 2: Assuming Run Mode Changes Take Effect on a Running Instance

The Mistake: Editing sling.properties while AEM is running and expecting configs to reload immediately.

Why It Happens: Run modes (especially author/publish) are evaluated largely at startup; some config changes won't fully apply without a restart.

Fix: Always restart the instance after changing run modes.

Pitfall 3: Overlapping Custom Run Modes Without Realizing It

The Mistake: Defining both config.publish.us/ and config.publish.eu/ folders, then accidentally starting an instance with -r publish,prod,us,eu (perhaps copy-pasted from a multi-region deployment script).

Why It Happens: AEM doesn't block this combination the way it blocks author+publish, so there's no hard error — configs silently merge/conflict.

Fix: Treat logically exclusive custom run mode groups (region, brand, tenant) with the same discipline as author/publish, even though AEM won't enforce it for you. Document which run mode groups are mutually exclusive in your project's README.

Pitfall 4: Confusing Port Number with Run Mode

The Mistake: Assuming an instance running on 4503 is automatically in publish mode.

Fix: Always explicitly verify active run modes via /system/console/vmstat, not by inferring from the port.

Pitfall 5: Trying to Change author/publish After the Fact

The Mistake: Attempting to convert an existing author instance into a publish instance by just changing the -r flag on restart.

Why It Happens: Misunderstanding that these are "install-time" run modes baked deeply into the initial repository setup and default configuration.

Fix: If you genuinely need a different instance type, provision a fresh instance rather than attempting to flip an existing one.


Key Takeaways

What Run Modes Are

  • String labels assigned at JVM startup (-r run mode1,runmode2,...) that determine which OSGi configurations and content get applied

  • Configuration folders use dot-suffix naming (config.author/, config.author.dev/) — multiple dots mean all those run modes must be active together

Pre-Built Run Modes

  • author and publish — the foundational, install-time, mutually exclusive instance-type run modes

  • dev, stage, prod — industry-standard environment tier run modes (convention, not hardcoded by AEM)

  • samplecontent / nosamplecontent — control demo content installation

  • Adobe reserves certain run mode namespaces for add-on products (Forms, Communities, Screens)

Custom Run Modes

  • Freely definable for region, brand, tenant, or any project-specific dimension

  • Passed the same way as built-in ones via -r

  • Install-time run modes are fixed once set (stored in sling.properties) and shouldn't be changed without reprovisioning

  • Combine cleanly with instance-type and environment run modes for layered configuration

Mutual Exclusion

  • author and publish must never both be active — AEM's architecture assumes an instance is exactly one or the other; combining them produces conflicting replication, security, and authoring configurations

  • Custom run mode groups representing incompatible contexts (e.g., region or brand) should be treated as mutually exclusive by convention, even though AEM doesn't technically block combining them

Ports

  • Run mode and port are independent settings — port never determines run mode

  • Convention: 4502 for author, 4503 for publish, with incrementing ports (4512, 4513, 4522, 4523...) for additional clustered or multi-region instances

  • Always pair run mode and port explicitly and consistently in startup scripts to avoid team confusion