Skip to main content

Lifecycle action specifications

Before you start

If you haven't already, read about scopes' main concepts.

Also, keep these references handy:

Design your action specifications​

Now that you have a scope specification, bring it to life by designing actions that nullplatform will invoke at different points in the scope's lifecycle.

Here are some key design questions:

QuestionGuidance
Which input parameters are required to create the scope?This defines the contents of the JSON schema under the attributes field.
What optional actions should be available?Think about actions that support specific operations, like adjusting traffic percentage during blue-green deployments.

Lifecycle: execution flow​

The execution flow for lifecycle actions is illustrated below:

Define all required actions​

Most scopes require at least these actions:

  • create or delete the scope
  • Handle deployments, like triggering initial deployments or finalizing blue-green ones

In addition, you can define optional custom actions to extend your scope’s functionality. This means that you'll likely have to design and create several actions for a scope.

Your actions should use one of the following types: create, update, or custom.

Action specification reference​

NameAction typeParametersDescriptionRequired
Create scopecreatescope_idTriggered during scope creation to provision infrastructure independent of app versions (e.g., DNS).Yes
Start initialcustomscope_id, deployment_idStarts an initial deployment, typically the first or one after a scope restart.Yes
Start blue greencustomscope_id, deployment_idInitiates a blue-green deployment.Yes
Switch trafficcustomscope_id, deployment_id, desired_trafficAdjusts traffic percentage during blue-green deployments.No
Finalize blue greencustomscope_id, deployment_idCleans up old infrastructure after blue-green deployment completion.Yes
Rollback deploymentcustomscope_id, deployment_idReverts to the previous deployment and removes the new infrastructure.Yes
Delete deploymentcustomscope_id, deployment_idDeletes deployment infrastructure when the active scope is stopped.No
Wait for instancescustomscope_id, deployment_id, readyWaits for instances to be ready before proceeding with deployment operations.No
Update scopeupdatescope_idUpdates the scope’s infrastructure if changes are required.No
Delete scopecustomscope_idDeletes app-version-independent infrastructure during scope deletion.Yes

Parameters​

Each action must define the following:

  • parameters: inputs required to execute the action (as a JSON schema)
UI Schema

See the UI schema reference section for more information on how to control the fields in the UI.

Creating action specifications​

To define the actions for your scope, use the CLI or API.

While not strictly required, most scopes rely on actions to create, update, or delete the scope and to manage scope workflows.

When using the UI, nullplatform automatically looks up the corresponding action specifications and creates instances as needed. If you're integrating programmatically, you’ll need to trigger these actions explicitly.

Action types

Use the type field on the action specification to distinguish between create, update, and custom actions.

Create scope​

np service specification action specification create \ 
--serviceSpecificationId $service-spec-id \
--body '{
"name": "Create scope",
"type": "create",
"parameters": { // defines the input requirements for the action
"schema": {
"type": "object",
"required": ["scope_id"], // required parameter to create a scope
"properties": {
"scope_id": {
"type": "string"
}
}
},
"values": {}
},
"results": {
"schema": {
"type": "object",
"properties": {}
},
"values": {}
}
}'

Start initial​

np service specification action specification create \
--serviceSpecificationId $service-spec-id \
--body '{
"name": "Start initial",
"type": "custom",
"parameters": { // defines the input requirements for the action
"schema": {
"type": "object",
"required": ["scope_id", "deployment_id"], // required parameters to start initial
"properties": {
"scope_id": {
"type": "string"
},
"deployment_id": {
"type": "string"
}
}
},
"values": {}
},
"results": {
"schema": {
"type": "object",
"properties": {}
},
"values": {}
}
}'

Start blue green​

np service specification action specification create \
--serviceSpecificationId $service-spec-id \
--body '{
"name": "Start blue green",
"type": "custom",
"parameters": { // defines the input requirements for the action
"schema": {
"type": "object",
"required": ["scope_id", "deployment_id"], // required parameters to start blue green
"properties": {
"scope_id": {
"type": "string"
},
"deployment_id": {
"type": "string"
}
}
},
"values": {}
},
"results": {
"schema": {
"type": "object",
"properties": {}
},
"values": {}
}
}'

Finalize blue green​

np service specification action specification create \
--serviceSpecificationId $service-spec-id \
--body '{
"name": "Finalize blue green",
"type": "custom",
"parameters": { // defines the input requirements for the action
"schema": {
"type": "object",
"required": ["scope_id", "deployment_id"], // required parameters to finalize blue green
"properties": {
"scope_id": {
"type": "string"
},
"deployment_id": {
"type": "string"
}
}
},
"values": {}
},
"results": {
"schema": {
"type": "object",
"properties": {}
},
"values": {}
}
}'

Rollback deployment​

np service specification action specification create \
--serviceSpecificationId $service-spec-id \
--body '{
"name": "Roll back deployment",
"type": "custom",
"parameters": { // defines the input requirements for the action
"schema": {
"type": "object",
"required": ["scope_id", "deployment_id"], // required parameters to roll back deployment
"properties": {
"scope_id": {
"type": "string"
},
"deployment_id": {
"type": "string"
}
}
},
"values": {}
},
"results": {
"schema": {
"type": "object",
"properties": {}
},
"values": {}
}
}'

Delete deployment​

np service specification action specification create \
--serviceSpecificationId $service-spec-id \
--body '{
"name": "Delete deployment",
"type": "custom",
"parameters": { // defines the input requirements for the action
"schema": {
"type": "object",
"required": ["scope_id", "deployment_id"], // required parameters to roll back deployment
"properties": {
"scope_id": {
"type": "string"
},
"deployment_id": {
"type": "string"
}
}
},
"values": {}
},
"results": {
"schema": {
"type": "object",
"properties": {}
},
"values": {}
}
}'

Update scope​

np service specification action specification create \
--serviceSpecificationId $service-spec-id \
--body '{
"name": "Update scope",
"type": "update",
"parameters": { // defines the input requirements for the action
"schema": {
"type": "object",
"required": ["scope_id"], // required parameters to update deployment
"properties": {
"scope_id": {
"type": "string"
}
}
},
"values": {}
},
"results": {
"schema": {
"type": "object",
"properties": {}
},
"values": {}
}
}'

Delete scope​

np service specification action specification create \
--serviceSpecificationId $service-spec-id \
--body '{
"name": "Delete scope",
"type": "custom",
"parameters": { // defines the input requirements for the action
"schema": {
"type": "object",
"required": ["scope_id"], // required parameters to delete deployment
"properties": {
"scope_id": {
"type": "string"
}
}
},
"values": {}
},
"results": {
"schema": {
"type": "object",
"properties": {}
},
"values": {}
}
}'

Wait for instances​

np service specification action specification create \
--serviceSpecificationId $service-spec-id \
--body '{
"name": "Wait for instances",
"type": "custom",
"parameters": { // defines the input requirements for the action
"schema": {
"type": "object",
"required": ["scope_id", "deployment_id"], // required parameters to wait for instances
"properties": {
"scope_id": {
"type": "string"
},
"deployment_id": {
"type": "string"
},
"ready": {
"type": "boolean",
"description": "Indicates whether instances should be ready"
}
}
},
"values": {}
},
"results": {
"schema": {
"type": "object",
"properties": {}
},
"values": {}
}
}'

Run scope actions in parallel​

By default, scope lifecycle actions are executed sequentially to ensure safety and predictability. However, some lifecycle operations can safely run in parallel.

With the parallelize flag, you can configure certain custom scope actions to run concurrently, improving deployment speed and throughput when actions don’t depend on each other.

When to use parallel execution

Parallel execution is valuable when lifecycle actions are independent and don’t modify the same resource at the same time. Typical use cases include:

  • Blue-green deployments: Triggering multiple rollout steps or health checks simultaneously.
  • Traffic management: Adjusting traffic for multiple services or endpoints in parallel.
  • Infrastructure operations: Running instance readiness checks (wait-for-instances) concurrently across deployments.

ℹ️ Best practice: Only parallelize lifecycle actions that are idempotent or operate on isolated resources. Keep sequential execution for steps like switch traffic or rollback deployment, where order and consistency matter.

How to enable parallel execution​

To mark a lifecycle action as parallelizable, set "parallelize": true in its action specification:

{
"actions": {
"wait-for-instances": { "parallelize": true },
"switch-traffic": { "parallelize": false }
}
}
  • parallelize: true → the action can run alongside other actions.
  • parallelize: false → the action must complete before others start.

This gives you fine-grained control over which lifecycle steps can safely overlap.

📖 See our API reference for more info.

Configure the maximum wait time for deployment start actions​

When a deployment of an agent-backed scope starts, nullplatform waits for its instances while the start action runs. By default, it waits up to 600 seconds (10 minutes).

If the limit is exceeded, nullplatform marks the running action as failed, adds the deployment message Instances didn't become healthy within the 10m limit (with your limit in place of 10m), and cancels the deployment. Then it runs Rollback deployment for blue-green deployments, or Delete deployment for initial ones.

Start actions that run long jobs, such as Terraform, may need more time. To raise (or lower) the limit, declare a max_wait_seconds integer property with a default value in the parameters.schema of the start action specification. It's a regular parameter, so you don't need to configure anything else.

PropertyTypeEffective rangeUsed when absent
max_wait_secondsinteger60 – 3600 seconds600 seconds
  • Declare it in the Start initial (start-initial) action specification for initial deployments, in the Start blue green (start-blue-green) action specification for blue-green deployments, or in both. It isn't read from any other action specification.
  • Only the property's default is used, and it must be a number. If the property or its default is missing, or the default isn't a number (for example, the string "1500"), the wait is 600 seconds. Values outside the 60 – 3600 range are clamped to the nearest limit.
  • The limit is the total time of the "waiting for instances" phase, counted from when the start action is triggered. If your scope also defines a Wait for instances (wait-for-instances) action, all of its runs count against the same limit: a run that returns ready: false doesn't reset it. The value is still read from the start action specification.
  • Your agent also receives max_wait_seconds in the action payload, as declared and without clamping. Your script can ignore it, since nullplatform enforces the wait itself.
  • The wait is read from the start action specification while the deployment waits, so changing the default also affects deployments that are already waiting.

Example​

Allow up to 25 minutes (1500 seconds) for the initial deployment of a scope whose start action runs Terraform:

{
"name": "Start initial",
"type": "custom",
"parameters": {
"schema": {
"type": "object",
"required": ["scope_id", "deployment_id"],
"properties": {
"scope_id": {
"type": "string"
},
"deployment_id": {
"type": "string"
},
"max_wait_seconds": {
"type": "integer",
"default": 1500,
"minimum": 60,
"maximum": 3600
}
}
},
"values": {}
},
"results": {
"schema": {
"type": "object",
"properties": {}
},
"values": {}
}
}

💡 Tip: Adding minimum and maximum to the property is optional, but it documents the supported range. Regardless of the schema, nullplatform clamps the wait to 60 – 3600 seconds.

To apply the same limit to blue-green deployments, add the same max_wait_seconds property to the parameters.schema of the start-blue-green action specification.