Skip to main content

Cloud-Ready Backend Code: Quality Gates and Common Pitfalls

Series: AEM Backend Advanced — Part 7

Updated 6 min readMarkdown
Part of seriesAEM Backend Advanced
Cloud-Ready Backend Code: Quality Gates and Common Pitfalls

On AEM as a Cloud Service, your code reaches Production only through a Cloud Manager pipeline, and that pipeline checks it. Some checks are about quality, some about compatibility, and some about patterns that are known to cause outages. Teams moving from AEM 6.5 often find that code that ran for years now fails the build. This post collects the rules and habits that make backend code Cloud-ready, so you can write it right the first time or find what to fix when migrating.

What the Pipeline Checks

A Cloud Manager pipeline builds your project, runs your unit tests, and then runs code quality scans (static analysis plus Adobe's own AEM-specific rules) and compatibility checks against the AEM SDK API. Findings are rated by severity. Critical findings stop the pipeline, while lower severities are reported for you to address.

Because rule names and thresholds change over time, treat the lists below as patterns to know, and read the current Cloud Manager documentation for the exact rules.

Patterns the Quality Rules Target

Pattern Why it's a problem What to do
A ResourceResolver that isn't closed Leaks resources and degrades the system over time Use try-with-resources, as in the service users post
HTTP calls without connect and read timeouts One slow partner can stall the whole site Set both, with values far below the 60-second maximum, as in the integrations post
Servlets registered by path Bypass the standard access control on resources Register by resource type
Dangerous Java calls (for example stopping threads or killing the JVM) Can destabilize a shared runtime Remove them. There's almost always a safer design
Using the Sling Scheduler for guaranteed work Runs on every instance, or not at all, on a cluster Use Sling Jobs
Implementing product APIs meant to be consumed Breaks when Adobe updates the platform Call them, don't implement them

Design Rules for a Cluster

These are not all machine-checked, but they decide whether your code behaves in production.

Be stateless. Don't keep important data in instance fields or on the local disk. Another instance won't have it, and the instance itself can disappear at any time.

Don't write to the local file system. Treat it as temporary. Store anything that matters in the repository or in an external service.

Assume several instances. Anything triggered by an event or a timer may run on more than one. Use jobs for "once" semantics, and make the work idempotent.

Expect old and new code to overlap. During a deployment, instances running the previous release and the new one serve traffic together for a while. Don't change a content structure or an API in a way that breaks the other version. Do such changes in two steps: first support both, then remove the old.

Don't depend on startup order. Services can appear in any sequence. Use optional or dynamic references where a missing service shouldn't be fatal.

Don't write to immutable areas. /apps and /libs can't be changed at runtime. Write to /content, /conf or /var.

Things That Change When Moving from 6.5

On 6.5 you could... On Cloud Service you...
Install a package or bundle by hand Deploy through the pipeline
Edit OSGi configuration on the server Commit .cfg.json files and deploy
Use loginAdministrative Use service users
Run a Commons Scheduler task Use Sling Jobs
Keep files on the disk Use the repository or an external store
Use any API in the product jars Use the AEM SDK API
Use custom run modes Use author, publish, and dev, stage, prod
Rely on replication agents Use the built-in content distribution
Add libraries freely Check each library is allowed and resolvable. Bundled third-party code may need review

Adobe's tools help with the audit. The Best Practices Analyzer scans a 6.5 instance and reports incompatible patterns, and the pattern detector flags specific code patterns that need changes. Run them early in a migration.

Java Version Differences

Cloud Service has moved to newer Java versions over time, and each step removes some older APIs. If you're upgrading a project:

  • Check which Java version your pipeline builds and runs with
  • Replace removed or restricted APIs
  • Update libraries whose old versions don't support the target version
  • Be careful with javax and Jakarta package names. Most AEM projects still use javax imports, and the move to Jakarta is only now arriving, so don't change imports unless your SDK version and archetype tell you to

Test Like the Pipeline Does

Running the checks locally saves a pipeline run:

mvn clean verify

Then:

  • Fix unit test failures first
  • Read warnings about unresolved imports or API usage. They usually mean something won't resolve at runtime
  • Deploy to a Dev environment before Stage, and watch the logs through one full cycle of the background work

A Practical Review Checklist

Use this in code review for any backend change:

  1. Every ResourceResolver is closed, or comes from the request
  2. Every outbound HTTP call has timeouts
  3. Servlets use resource types, not paths
  4. No new Commons Scheduler tasks for important work
  5. Background work is idempotent and runs through Sling Jobs
  6. Configuration comes from .cfg.json with run modes and environment variables, with no secrets in Git
  7. No local file writes, no static mutable state of importance
  8. No assumptions about instance count or startup order
  9. Logging has no secrets and uses the right levels
  10. A unit test covers the main path and one failure path

Common Pitfalls

  • "It passed locally." The local SDK is one instance with relaxed behavior
  • Fixing the warning but not the cause. For example catching an exception to silence a rule
  • A big-bang change. Large, risky deployments are harder to roll forward safely than small ones
  • Ignoring non-critical findings forever. They accumulate and later block you
  • Skipping the Dev environment. Cluster behavior only shows up there

What's Next

You've now seen the pieces: OSGi, configuration, service users, servlets, jobs, workflows, integrations, security and Cloud-ready habits. The final post puts them together into one worked backend example.


Next in this series: [Putting It Together: A Worked Backend Example]

About the author

  • AEM Technical Lead experienced with building and architecting solutions on AEM Sites and Assets. Sharing practical tutorials, real-world implementation lessons, and best practices to help fellow developers and leads navigate AEM.

What was the first Cloud Manager finding that surprised you, and how did you fix it? If you're migrating from 6.5, which pattern in your code base worries you most?

AEM Backend Advanced

Part 7 of 8

Factory configurations, filters and listeners, jobs, workflows, integrations, security and Cloud-ready code for AEM as a Cloud Service, with 6.5 differences.

Up nextPutting It Together: A Worked Backend ExampleSeries: AEM Backend Advanced — Part 8