Migrate from node-bt
Use this guide to replace an existing node-bt Reactor or Proxy code transform with a Node.js runtime image. Migrate away from the node-bt runtime as soon as possible to avoid disruption.
We recommend creating a replacement Reactor or Proxy resource and moving traffic only after it passes your tests. Keeping the existing node-bt resource unchanged gives you a direct rollback path during the cutover.
1. Translate the Runtime Configuration
Choose a Node.js runtime image. The available images share the same runtime options, provisioning states, code contracts, and security controls. Match the image to the Node.js version used to develop and test your code.
Translate the legacy resource settings as follows:
node-bt setting | Node.js runtime replacement |
|---|---|
Missing runtime or runtime.image: "node-bt" | Set runtime.image to a Node.js runtime image. |
Packages from the node-bt whitelist | Add every package used by the code to runtime.dependencies with an exact pinned version. Use runtime.resolutions only when overriding a transitive dependency. |
Linked application.id used for Basis Theory API access | Add every permission required by the code to runtime.permissions, then initialize the API client from event.applicationOptions. If the linked Application uses Access Rules, follow Migrate an Access Rule with a Reveal Transform to determine whether runtime permissions can preserve its authorization. |
| Linked Application ID used as a value in your own logic | Store the value in the resource configuration and read it from event.configuration. This does not grant the linked Application's permissions or reproduce its API key. |
| Fixed runtime behavior | Configure timeout, resources, and warm concurrency for the workload. |
Legacy asynchronous Reactor using callback_url | Set runtime.async: true, invoke the Reactor through /react-async, and retrieve the result with the returned request ID. /react now rejects callback_url with a 400 error. |
Migrate an Access Rule with a Reveal Transform
Some linked Applications use an Access Rule that combines token:read with the reveal transform to return plaintext Token data.
Replace a root Container rule with runtime permissions
An Access Rule scoped to the root Container (/) applies to all Tokens in the Tenant. Replace this rule with Node.js runtime permissions. Add every permission required by the code, including token:read and token:reveal when plaintext retrieval is required. If the runtime only requires masked Token data, include token:read without token:reveal.
Use this option only when the Application's complete Access Rule set permits plaintext access to every Token in the Tenant.
For a Reactor, set the permissions on its runtime:
{
"runtime": {
"image": "node24",
"permissions": ["token:read", "token:reveal"]
}
}
For a Proxy, set the permissions on every code transform that retrieves token data:
{
"options": {
"runtime": {
"image": "node24",
"permissions": ["token:read", "token:reveal"]
}
}
}
Initialize the SDK with the runtime credentials:
const { BasisTheoryClient } = require("@basis-theory/node-sdk");
module.exports = async function (event) {
const client = new BasisTheoryClient({
apiKey: event.applicationOptions.apiKey,
baseUrl: event.applicationOptions.baseUrl,
});
// Use the client here.
};
token:reveal is currently available only to Node.js runtimes. It cannot be granted directly to an Application as a permission.
Preserve a container-scoped Access Rule
Runtime permissions cannot be scoped to a Container. If the existing rule uses a Container other than /, keep the Private Application and store an Application API key in the Reactor or Proxy's encrypted configuration:
{
"configuration": {
"BASIS_THEORY_API_KEY": "<PRIVATE_API_KEY>"
}
}
Initialize the SDK with the configured key:
const { BasisTheoryClient } = require("@basis-theory/node-sdk");
module.exports = async function (event) {
const client = new BasisTheoryClient({
apiKey: event.configuration.BASIS_THEORY_API_KEY,
baseUrl: event.applicationOptions.baseUrl,
});
// Use the client here.
};
Requests made with this key continue to use the Application's Access Rules. If you need help migrating a more complex authorization model, contact us.
2. Translate the Code Contract
The supported Node.js images use an event-based contract. Update each legacy input and output used by the code.
Reactor Code
node-bt contract | Node.js runtime contract |
|---|---|
req.args | event.req |
req.configuration | event.configuration |
req.bt | Initialize @basis-theory/node-sdk from event.applicationOptions when using runtime permissions, or from an Application API key in event.configuration when preserving container-scoped Access Rules. |
return { raw: value } | return { res: { body: value } } |
return { tokenize: value } | Create the token explicitly with the Node.js SDK, then include the token result you need in res.body. Add token:create to runtime.permissions. |
| Application logging | Use event.logger.info(), event.logger.warn(), or event.logger.error(). |
See the complete Reactor code contract, including response headers and status codes.
module.exports = async function (event) {
const { req, configuration, logger } = event;
logger.info("Processing request");
return {
res: {
body: {
customer_id: req.customer_id,
service: configuration.SERVICE_NAME,
processed: true
},
statusCode: 200
}
};
};
Proxy Code Transforms
node-bt contract | Node.js runtime contract |
|---|---|
Request transform input at req.args | event.req |
Response transform input at req.args | event.res |
Request transform returns { body, headers } | Return { req: { body, headers } }. |
Response transform returns { body, headers } | Return { res: { body, headers } }. You can also set res.statusCode. |
Throw CustomHttpResponseError to skip the destination | Return { res: { body, headers, statusCode } } from the request transform. |
See the complete Proxy request transform contract, response transform contract, and skip request behavior.
module.exports = async function (event) {
const { body, headers } = event.req;
return {
req: {
body,
headers: {
...headers,
"X-Processed-By": "Basis Theory"
}
}
};
};
3. Create the Replacement Resource
Create the replacement with the translated code and runtime configuration:
- For a Reactor, use the Create Reactor API and copy the existing name and configuration values that still apply.
- For a Proxy, use the Create Proxy API. Copy the destination, authentication setting, configuration, and non-code transforms that still apply. Add the translated runtime options to each code transform.
The replacement receives a new Reactor ID or Proxy key. Save that identifier for the cutover. If the original Proxy has a custom hostname that needs to be transferred to the replacement Proxy, save the old and replacement Proxy IDs.
Creating a resource with a Node.js runtime image provisions it asynchronously. Wait until its state is active before invoking it. If provisioning fails, inspect the resource's requested object for the deployment error.
4. Validate the Replacement
Exercise the replacement without changing production traffic:
- Test successful requests and the error paths expected by callers.
- Compare the body, headers, and status code with the legacy behavior.
- Confirm every Basis Theory API call succeeds with the configured runtime permissions.
- For a Proxy, confirm the destination receives the expected request and the caller receives the expected response.
- For an asynchronous Reactor, verify invocation, result retrieval, webhook handling, partial results, failures, and timeouts.
5. Cut Over with a Rollback Path
After validation:
- For a Reactor, update callers to use the replacement Reactor ID.
- For Proxy callers using a key, update callers to send the replacement key in the
BT-PROXY-KEYheader or corresponding SDK option. - For Proxy callers using a Basis Theory-generated Proxy URL, update callers to use the replacement Proxy's generated URL.
- For Proxy callers using a custom hostname, complete the custom hostname transfer and verification procedure. The callers continue using the same hostname.
Monitor the replacement after the cutover. Keep the node-bt resource unchanged until you are confident the migration is stable. If an issue occurs, restore the previous Reactor ID or Proxy key, or follow the custom hostname rollback steps to move traffic back.
6. Delete the Legacy Resource
Delete the old resource only after all callers use the replacement and the rollback period is complete. If the legacy Proxy has a custom hostname that needs to be transferred to the replacement Proxy, complete and verify the transfer before deleting the legacy Proxy. Use the Delete Reactor or Delete Proxy API.
If you need help translating a legacy contract or authorization model, contact support@basistheory.com.