API Maker

The backend engine for the AI era

Security

Sandboxes

Your code runs in Docker containers, apart from the API Maker process, with time limits and automatic replacement.

Custom APIs, hooks, event listeners, schedulers, migrations and test cases run in sandbox containers, not in the API Maker process. Every language has a sandbox of its own, every run has a time limit, a stuck sandbox is replaced, and each account chooses the runtime, the version and the packages its images are built with. Sandboxes keep faulty code away from the engine. They are not a wall against hostile code: give code access only to people you trust.

See it live

Step through it, slow it down, or open the full canvas.

api-maker/features/secure-sandboxLive
  • Request
  • TCP
  • g call, in the sandbox
  • Timeout
Timeout
13000ms, default
Sandboxes
1running
Replaced
0after a timeout
User code
0in API Maker

Your code runs outside API Maker. Custom APIs, hooks, event listeners, schedulers, migrations and test cases run in Docker containers, each language in a sandbox of its own, which every thread of API Maker uses. API Maker hands the request to the sandbox over TCP and gets the answer back.

How it works

  1. Your code runs outside API Maker.

    Custom APIs, hooks, event listeners, schedulers, migrations and test cases run in Docker containers, each language in a sandbox of its own, which every thread of API Maker uses. API Maker hands the request to the sandbox over TCP and gets the answer back.

  2. API Maker is inside the sandbox too.

    The sandbox holds API Maker itself, as a library of the runner of your language. g.sys.db.query is a function call there: it runs the real API with its checks, and reads the database from the sandbox.

  3. Every run has a time limit.

    13 seconds by default. Change it per request with the x-am-sandbox-timeout header, or in the settings of a custom API, a scheduler or a listener.

  4. A stuck sandbox is replaced.

    It gets no new requests, the ones inside it finish, then it is removed and a new sandbox takes its place. The time to get a sandbox is not counted in the logs.

  5. Your own image, your own packages.

    Each language of an account gets an image built from its runtime, your packages and your Dockerfile, on every server. Save the settings and the sandboxes start anew from the new image.

  6. Tune it to your load.

    A runtime and a version per language, the sandbox count of every server or of each one, a separate sandbox for a heavy API, or the native process for code you trust.

What you get

Apart from API Maker

An endless loop or a crash in your code stays in its container, and API Maker keeps serving the other requests. A container has no memory limit of its own: code on Node.js has a heap limit, code of the other languages uses the memory of the server.

Separate sandbox groups

Give a heavy custom API a sandbox group of its own, with its own runtime, version, packages and Dockerfile.

Real debugging

Turn on debugging and stop your code at breakpoints, in every language and on the native process too, right in the admin panel. The debug engine is published nowhere: the server alone reaches it, through the agent of the sandbox.

An example

A heavy report next to fast APIs

Generating PDFs needs a big package and a lot of memory. In its own sandbox group, it gets its package and its own sandboxes, while every other API keeps its small, fast ones.

A custom API with a sandbox group of its owncustom-api-settings.ts
import * as T from 'types';let customApi: T.ICustomApiSettingsTypes = {    name: 'Invoice PDF',    requestMethod: T.ERequestMethod.POST,    path: '/invoice-pdf',    customApiTimeoutInSeconds: 60,    separateSandboxSettings: {        enableSeparateSandboxForThis: 'pdf_group',        sandboxCount: 1,        packages: { allowAllPackagesOfAdmin: false, sandboxPackages: [{ name: 'pdfkit', version: '0.15.0' }] },    },    errorList: [],};module.exports = customApi;

Good to know

  • The containers are started privileged and without a memory limit, so treat the sandbox as a guard against faulty code, not against hostile code: only give code access to people you trust, and give separate clients separate servers.
  • runOnNativeProcess skips the sandbox: the code then runs on the server itself, in a runner shared by every account, and can slow the whole server.
  • Sandbox containers need Docker on the server. API Maker Launchpad sets it up.

Questions

How many sandboxes run?

One by default (Auto): on each server, the first request of a language of an account starts one sandbox, and every thread of the API Maker process uses it. A sandbox does not belong to a thread. It opens more runners while all of its runners are busy, up to as many as the server has CPU cores. Set a higher sandbox count in Sandbox settings, for every server or for one, and more sandboxes start while there is work. Idle sandboxes go after the minutes you set, or never. A sandbox group has a pool of its own, and a request waits when everything is busy.

How does code in the sandbox reach my databases?

Through g.sys.db. The sandbox holds API Maker itself, as a library of the runner of your language: the call is a function call inside the sandbox, which runs the real API with its checks and reads the database from there.

Can I change the time limit of one call?

Yes. Send x-am-sandbox-timeout in milliseconds, or set the limit in the settings of the custom API, scheduler or listener.