Maven profiles let you keep one pom.xml while adapting builds for different environments such as local development, CI, testing, or production. You will learn where profiles can be defined, how activation works, and how to use profiles without hurting build portability.
Originally published on 2010-04-14; fully revised and updated.
Reference basis: Apache Maven User Guide concepts for profiles, updated for practical DevOps usage. Original post: Profiles in Maven – How to Build Maven Profile?. Maven project site: Apache Maven.

What Maven profiles are and when to use them
A profile is a conditional block of Maven configuration. When active, it can add or override parts of the build (properties, dependencies, plugins, repositories, and more) for a specific context.
- Use profiles when builds differ by environment (for example, local vs CI).
- Use profiles to avoid maintaining multiple POM files with
-f. - Prefer profiles for complementary configuration, not for creating unrelated builds from one project.
Where Maven profiles are defined
Maven supports project, user, and global profile locations. Older Maven-era material also mentions a separate profiles.xml descriptor.
| Profile type | Defined in | Scope | Typical use |
|---|---|---|---|
| Per-project | pom.xml | Shared in source control | Project-specific dependencies, plugins, and properties |
| Per-user | ${user.home}/.m2/settings.xml | Single developer or CI agent | Local paths, credentials references, machine-specific defaults |
| Global | ${maven.home}/conf/settings.xml | All users of one Maven installation | Organization-wide defaults on managed hosts |
| Legacy descriptor | profiles.xml in project base directory | Historical pattern | Seen in older Maven 2 documentation; verify current support |
How profile activation works
Profiles can be activated explicitly from the command line or automatically through activation rules (JDK, OS, property, file presence/missing, or active-by-default behavior).
flowchart TD
A[Run mvn command] --> B[Load project profiles]
B --> C[Load user and global settings profiles]
C --> D{Any -P flags}
D -- Yes --> E[Apply explicit activate or deactivate]
D -- No --> F[Evaluate activation rules]
F --> G[Check jdk os property file conditions]
G --> H[Apply activeByDefault when applicable]
E --> I[Merge into effective pom]
H --> I
I --> J[Execute build lifecycle]
Important behavior: a profile with activeByDefault is typically deactivated when another profile in the same POM becomes active.
| Activation method | How to set it | Example | Best use |
|---|---|---|---|
| Explicit CLI | -P option | -Pdev,test | Temporary run-time choice |
| Settings default | <activeProfiles> in settings.xml | <activeProfile>corp</activeProfile> | User or machine defaults |
| System property | <activation><property> | -Denvironment=test | CI-driven environment selection |
| JDK | <activation><jdk> | 17 or range | JDK-specific build behavior |
| OS | <activation><os> | <family>Windows</family> | Platform-specific tooling |
| File exists/missing | <activation><file> | <missing>target/...</missing> | Generated-artifact or workspace checks |
Example profile configuration in pom.xml
<profiles>
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<app.env>dev</app.env>
</properties>
</profile>
<profile>
<id>test</id>
<activation>
<property>
<name>environment</name>
<value>test</value>
</property>
</activation>
<properties>
<app.env>test</app.env>
</properties>
</profile>
<profile>
<id>windows-build</id>
<activation>
<os>
<family>Windows</family>
</os>
</activation>
</profile>
<profile>
<id>generate-wsdl</id>
<activation>
<file>
<missing>target/generated-sources/wsdl.marker</missing>
</file>
</activation>
</profile>
</profiles>Code language: HTML, XML (xml)
For environment variables, Maven exposes them as properties prefixed with env. (for example, env.FOO).
Command-line usage: activate, deactivate, inspect
# Activate one or more profiles
mvn clean package -Pdev
mvn clean verify -Pdev,test
# Trigger property-based activation
mvn clean verify -Denvironment=test
# Deactivate profiles (quote ! in shells that treat it specially)
mvn clean package -P '!dev'
mvn clean package -P '!dev,!windows-build'
# Inspect profile resolution
mvn help:active-profiles
mvn help:all-profilesCode language: PHP (php)
Using settings.xml for user or machine-specific profiles
<settings>
<activeProfiles>
<activeProfile>corp-network</activeProfile>
</activeProfiles>
<profiles>
<profile>
<id>corp-network</id>
<properties>
<repo.mirror.enabled>true</repo.mirror.enabled>
</properties>
</profile>
</profiles>
</settings>Code language: HTML, XML (xml)
Keep secrets and machine-only values in settings files, not in project pom.xml.
Best practices for reliable team builds
- Prefer profile-driven properties over hardcoded absolute filesystem paths.
- Use clear profile IDs such as
dev,test,ci,prod. - Avoid unnecessary changes to artifact coordinates across profiles.
- Document which profiles CI uses, and verify with
mvn help:active-profiles. - Keep team-shared behavior in
pom.xml; keep user/machine behavior insettings.xml. - Treat legacy
profiles.xmlusage as technical debt and confirm support before relying on it.
I’m Rajesh Kumar, a DevOps, SRE, DevSecOps, Cloud, and Platform Engineering expert passionate about sharing practical knowledge, real-world experiences, and industry best practices. I have worked at Cotocus and regularly write about technology, travel, investing, health, product reviews, and digital marketing through my various platforms.
I publish technical articles at DevOps School, travel stories at Holiday Landmark, stock market insights at Stocks Mantra, health and fitness guidance at My Medic Plus, product reviews at TrueReviewNow, and SEO and digital marketing strategies at Wizbrand.
Find Trusted Cardiac Hospitals
Compare heart hospitals by city and services — all in one place.
Explore Hospitals