Move the Service to CloudHub
Prepare external persistence, trusted caller context and complete configuration before promoting an orders candidate.
A local order remains available because the same runtime can still open the same H2 file. A replacement cloud replica cannot be assumed to inherit that file. Moving the archive is therefore only part of moving the service.
The CloudHub reference project replaces H2 with PostgreSQL and removes the local reset, failure-injection and synthetic-principal routes. It keeps the accepted-order, request-result and outbox-write responsibilities. Those source changes make its requirements concrete; they do not establish a successful deployment or PostgreSQL acceptance run.

Prepare the cloud project in ACB
Open book/platform/cloudhub with File → Open Folder. Use Explorer to inspect README.md, pom.xml, the schema and deploy-inputs.example.properties before opening the application canvas. In Global Configurations, compare the PostgreSQL connection and HTTP Listener with the H2 and loopback connections from the local chapters. Follow orders-api into its acceptance flows; confirm that local reset and synthetic-principal routes are absent.
Use ACB’s integrated terminal for the documented Maven packaging and promotion commands. ACB can offer deployment commands, but this exercise uses the supplied promotion script so the artifact identity and complete property map remain explicit. Packaging is a local preparation step. Exchange publication and deployment require the authorized sandbox described below; a successful editor build does not substitute for them.
Prepare the environment before deploying
You need an authorized Anypoint organization and sandbox, a target with capacity, an available Java 17/Mule runtime image, an API instance, configured identity policies and a reachable PostgreSQL database. Apply the supplied schema through the database’s migration procedure. Provide a catalogue implementing the sample /catalogue response and the chosen service-authentication contract.
The reference uses the same catalogue prices for all tenants. It does not implement negotiated tenant pricing. If that is required, propagate trusted tenant context to an authenticated catalogue contract and test isolation as carefully as the cache exercise did.
The listener binds to 0.0.0.0:8081 so platform ingress can reach it — a listener bound only to loopback can answer perfectly well on the machine itself while refusing everything that arrives from outside it. The local chapters bind loopback deliberately, to keep their diagnostic routes on the development machine. Changing the bind address without removing those diagnostics would expose a different service than intended.
Review the full deployment inputs
Example 067 — Identify a CloudHub deployment
Source: platform/cloudhub/deploy-inputs.example.properties.
# Template only: resolve from your account; no deployment has been performed.
exchange.organizationId=REQUIRED_ORGANIZATION_ID
exchange.repositoryUrl=https://maven.anypoint.mulesoft.com/api/v3/organizations/REQUIRED_ORGANIZATION_ID/maven
deploy.controlPlane=https://anypoint.mulesoft.com
deploy.environment=Sandbox
deploy.target=REQUIRED_TARGET
deploy.application=REQUIRED_UNIQUE_NAME
deploy.runtimeImage=REQUIRED_AVAILABLE_4_12_3_JAVA17_IMAGE
deploy.vCores=REQUIRED_CAPACITY
deploy.apiId=REQUIRED_API_INSTANCE
deploy.catalogueHost=REQUIRED_CATALOGUE_HOST
deploy.dbUrl=REQUIRED_POSTGRESQL_TLS_JDBC_URL
deploy.dbUser=REQUIRED_DATABASE_USER
# Secrets: MULE_CONNECTED_APP_ID, MULE_CONNECTED_APP_SECRET, ORDERS_DB_PASSWORD.
# This file documents inputs; Maven does not automatically load it.
These application-defined names are consumed by the checked-in POM through Maven properties. The .properties file documents the required inputs; Maven does not automatically load it. Supply them through the controlled release job or explicit -D arguments, with secrets supplied through the protected environment.
The POM uses cloudhub2Deployment, pins Mule Maven Plugin 4.10.0 and selects the target, environment, runtime image, Java version and capacity separately. It also declares Exchange distribution management and a complete application-property map. The connected-app identity used to deploy is distinct from the callers’ identities and the database credential.
When a CloudHub redeployment supplies properties or secureProperties, the supplied set replaces existing configured values. Omitting both preserves existing values. This reference chooses a complete set, so a missing database property must be caught before deployment. CloudHub deployment parameters.
Promote a fixed application archive
A second build can resolve different dependencies, or run with different settings, even when the source looks unchanged — so the artifact to promote is the one that passed its tests, with environment configuration injected around it rather than baked into it. CloudHub deployment consumes an application published to Exchange. Resolve the organization’s coordinates and repository endpoint, publish the authoritative candidate, and retain its digest and test evidence. Use the direct mule:deploy goal for promotion of that candidate; a new lifecycle build creates another archive whose identity must be established again.
The companion platform/cloudhub/promote.sh invokes that direct goal and requires the machine-identity and database-secret environment values. It does not publish an artifact, provision infrastructure or configure API policies. Chapter 27 supplies the local validation pipeline and explains the release record that a deployment job must consume.
Check more than process health
Three results are worth keeping apart. Packaging produces the archive; a successful deployment establishes that the archive can start in a particular environment; a successful order through the public endpoint adds evidence that ingress, configuration and downstream access work together. Collapsing them into one green tick is what makes a failed rollout hard to locate — ingress can be entirely healthy while the dependency behind it is unreachable.
First inspect the deployment’s runtime and policy readiness. Then send a controlled owned order through the public endpoint and retrieve it. Test foreign ownership, invalid token, invalid command, repeated command, conflict and a dependency failure. Observe the database independently after the injected failure cases appropriate to that sandbox.
The local H2 tests establish the learning implementation’s behavior on H2. PostgreSQL constraints, driver errors and concurrent claim recovery need their own run. The same SQL intent is not proof of identical error mapping or isolation behavior.
The cloud reference writes outbox intent but does not start a dispatcher. Choose its publication target and ownership topology, deploy that component and test recovery before promising fulfillment. A second intake replica does not elect a dispatcher. Until that path is established, pending outbox age is unfinished integration work that must remain visible.
Diagnose the boundary that failed
| Observation | Investigate |
|---|---|
| Archive does not package | POM, dependencies, plugin/runtime compatibility |
| Deployment cannot select target | Machine permissions, environment, capacity, runtime image |
| Application starts but ingress fails | Bind address, ingress route, TLS and policy readiness |
| Request reaches flow but persistence fails | Database route, trust, credential, schema and driver |
| Orders commit but never reach a receiver | Dispatcher ownership, destination, outbox age and acknowledgement |
If the application never starts, read the first meaningful startup error rather than the last, because later exceptions are often consequences of a missing property or a failed global configuration. Redeploying the same archive cannot repair a missing secret — and changing the archive and the secret together makes it impossible to say which one repaired the deployment.
A green health route proves only its own path. Use a narrow controlled business request as well, with cleanup appropriate to the sandbox rather than the public diagnostic reset endpoint from the local book. Give that request synthetic data: a smoke check that depends on a real customer’s order staying unchanged will eventually report a deployment failure that never happened. Read the numbers together as well — low latency after a release can mean the new version is rejecting requests immediately, and a low error count can mean traffic never reached it.
Replacement and scaling change state assumptions
A second replica helps only when another instance can do useful work — if both wait on the same unreachable database, a higher count just produces more waiting requests. Capacity planning starts by naming what actually runs out: CPU, heap, connections, downstream throughput or time. Every scheduled or polled activity deserves the same review as the HTTP flows before that count goes up, because if a retry can submit A-1001 twice, scaling should not quietly turn that into two orders.
Local files, caches and runtime queues then belong to their actual lifecycle. Retain authoritative orders, request results, source exports and recovery evidence in services whose durability fits the replacement scenario. A warm local cache test says nothing about a multi-replica cold start.
Runtime Fabric changes which infrastructure and operations the organization owns. The application still needs compatible configuration, reachable dependencies and recovery tests, while the team also owns the selected cluster, network and storage responsibilities. “We have Kubernetes” does not establish that the orders API is reachable there, so the platform team and the integration team need a concrete handoff — who answers when the application is healthy and ingress is not? Neither target removes the business need to distinguish accepted, published and fulfilled.
Try it
1. Replace the replica. Which local state cannot simply be assumed to survive?
Show answer
The local H2 file, diagnostic files, transient VM messages and in-memory caches. Authoritative business state and replay evidence need persistence outside the replaced instance’s lifecycle.
2. Supply half a property map. Why is preserving yesterday’s database password not a safe assumption?
Show answer
Supplying a CloudHub properties or secureProperties set replaces the configured set rather than merging omitted values. Provide a complete versioned configuration or intentionally manage the whole configuration externally.
3. Read a green deployment. What remains unproved when the app starts but no outbox dispatcher exists?
Show answer
Publication and downstream progress. Intake can commit pending intent while nothing delivers it. Deploy and test a declared dispatcher/receiver path before promising fulfillment.
Not run. Exchange publication, PostgreSQL execution, CloudHub deployment, policy enforcement, ingress and replica replacement have not been executed for this edition. The complete reference project and inputs are supplied for environment acceptance, not labeled as local-test results.
Comments