How can I communicate to another deployed app in the same runtime
Opscotch 3.1.1 adds two distinct ways for deployments in the same runtime to talk to each other. They solve different problems, and it helps to treat them as separate tools rather than variants of the same feature.
Mechanism 1: In-Process HTTP Routing
Use this when the caller already works in HTTP terms and you want to keep that shape. The calling workflow still builds a URL and the receiving workflow still exposes an HTTP trigger, but the bootstrap routes the traffic in-process instead of over the network.
Caller bootstrap
{
"allowExternalHostAccess": [
{
"id": "otherhost",
"transport": "inProc",
"inProcServerId": "inProcOnly",
"inProcDeploymentId": "deployment2"
}
]
}
transport: "inProc" switches the host entry from normal HTTP to internal routing. Per the bootstrap schema, inProcServerId is required for this mode, and inProcDeploymentId can point the call at another deployment in the same runtime.
Receiver bootstrap
{
"allowHttpServerAccess": [
{
"id": "inProcOnly",
"inProcOnly": true
}
]
}
inProcOnly: true means the server is available only for internal routing and does not bind a network port.
Workflow shape
Caller:
{
"stepId": "cross-deploy-forward",
"trigger": {
"http": {
"method": "GET",
"path": "/ping",
"server": "deployment1"
}
},
"urlGenerator": {
"script": "context.setUrl(\"otherhost\", \"/pong\")"
}
}
Receiver:
{
"stepId": "pong",
"trigger": {
"http": {
"server": "inProcOnly",
"path": "/pong",
"method": "GET"
}
},
"resultsProcessor": {
"script": "context.setBody(\"pong\");"
}
}
When to use it
- You already have HTTP-triggered workflows and want to preserve them.
- You want bootstrap-only rerouting without rewriting the caller into
allowDeploymentAccess. - You want internal routing without opening an external port.
This is still HTTP-style communication. The key difference is that transport is internal to the runtime.
Mechanism 2: Direct Cross-Deployment sendToStep with a deploymentAccess Trigger
Use this when you control both deployments and want an explicit deployment-to-deployment call path. This does not go through HTTP routing. Instead, the caller uses a bootstrap-defined allowDeploymentAccess id and the receiver must expose a deploymentAccess trigger.
Caller bootstrap
{
"allowDeploymentAccess": [
{
"id": "otherDeployment",
"deploymentId": "deployment2",
"access": "call"
}
]
}
Receiver bootstrap
{
"allowDeploymentAccess": [
{
"id": "remoteDeployment",
"deploymentId": "deployment1",
"access": "receive"
}
]
}
Schema and workflow rules matter here:
access: "call"requiresdeploymentId.access: "receive"also requiresdeploymentIdunlessanyDeployment: true.- The receiving workflow step must use
trigger.deploymentAccess.ids.
Workflow shape
Caller:
{
"stepId": "cross-deploy-forward",
"resultsProcessor": {
"script": "context.setBody(context.sendToStep(\"otherDeployment\", \"ping\", \"\").getBody());"
}
}
Receiver:
{
"stepId": "ping",
"trigger": {
"deploymentAccess": {
"ids": ["remoteDeployment"]
}
},
"resultsProcessor": {
"script": "context.setBody(\"pong\");"
}
}
The API reference for Opscotch 3.1.1 exposes these overloads:
context.sendToStep(deploymentAccessId, stepName, body)context.sendToStepAndForget(deploymentAccessId, stepName, body)
The blocking form returns a JavascriptStateContext, so reading the response body with .getBody() is valid. The call will only land on steps that are explicitly exposed through a deploymentAccess trigger.
When to use it
- You want a first-class cross-deployment contract.
- You control both the caller and receiver.
- You do not need to preserve HTTP listener semantics between the two deployments.
Timing
Refer to boot time optimizations for information on how to sequence deployment loading when cross-deployment availability are a concern.
Error Codes
The 3.1.1 deployment-access errors tied to this feature are:
| Code | Meaning |
|---|---|
DA1 | The caller referenced a missing allowDeploymentAccess id |
DA2 | The receiver denied deployment access |
DA3 | The target deployment was not available |
These apply to direct cross-deployment access and are useful when validating caller/receiver bootstrap alignment.
Comparison
| Aspect | In-Process HTTP Routing | Direct Cross-Deployment sendToStep |
|---|---|---|
| Bootstrap feature | allowExternalHostAccess + allowHttpServerAccess | allowDeploymentAccess |
| Receiver trigger | http | Required: deploymentAccess |
| Calling code shape | context.setUrl(...) and normal HTTP step flow | context.sendToStep(...) or context.sendToStepAndForget(...) |
| HTTP semantics | Preserved | Not used |
| Best fit | Preserve existing HTTP workflow design | Explicit internal orchestration |
| Coupling | Looser | Tighter |
Practical Guidance
Choose in-process HTTP routing when the existing contract is already HTTP and you want the least workflow churn.
Choose direct cross-deployment sendToStep when you are designing the interaction intentionally inside Opscotch and want the bootstrap to declare that relationship directly.