Skip to main content

How can I communicate to another deployed app in the same runtime

· 4 min read
Jeremy Scott
Co-founder

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" requires deploymentId.
  • access: "receive" also requires deploymentId unless anyDeployment: 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:

CodeMeaning
DA1The caller referenced a missing allowDeploymentAccess id
DA2The receiver denied deployment access
DA3The target deployment was not available

These apply to direct cross-deployment access and are useful when validating caller/receiver bootstrap alignment.

Comparison

AspectIn-Process HTTP RoutingDirect Cross-Deployment sendToStep
Bootstrap featureallowExternalHostAccess + allowHttpServerAccessallowDeploymentAccess
Receiver triggerhttpRequired: deploymentAccess
Calling code shapecontext.setUrl(...) and normal HTTP step flowcontext.sendToStep(...) or context.sendToStepAndForget(...)
HTTP semanticsPreservedNot used
Best fitPreserve existing HTTP workflow designExplicit internal orchestration
CouplingLooserTighter

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.