Getting started with Serverless Runs
Run code in our lightweight serverless environment.
Sign up at admin.freestyle.sh, create an api key, and configure it in your environment.
FREESTYLE_API_KEY=your-api-keynpm i freestyle-sandboxes@betaServerless runs allow you to execute code in a lightweight javascript environment.
Running Code
To create an Serverless Run, provide a script exporting the function you want to run.
You'll be returned the result of the function execution along with any logs
generated during the run. The result will be serialized using JSON.stringify,
so make sure your return value is serializable.
import { freestyle } from "freestyle-sandboxes";
const { result, logs } = await freestyle.serverless.runs.create<string>({
code: `export default () => {
return "Hello from Serverless!";
}`,
config: {
timeout: 3000, // Optional timeout in milliseconds
}
});
console.log(result); // "Hello from Serverless!"
console.log(logs); // Logs generated during executionNode Modules
Serverless runs have first class support for node modules. You can specify the modules
you want to use in the config.nodeModules field. These modules will be cached
for future runs, making subsequent executions faster.
import { freestyle } from "freestyle-sandboxes";
const { result } = await freestyle.serverless.runs.create({
code: `
import { z } from 'zod';
export default () => {
const User = z.object({ name: z.string(), email: z.string().email() });
return User.parse({ name: "Alice", email: "alice@example.com" });
}
`,
config: {
nodeModules: {
zod: "3.22.4",
},
},
});Peer dependencies are automatically resolved, but you can also specify how they
should be handled using the peerDependencyResolution field.
Env Variables
You can also pass environment variables to your serverless runs using the config.env field.
import { freestyle } from "freestyle-sandboxes";
const { result } = await freestyle.serverless.runs.create({
code: `
export default () => {
return process.env.MY_SECRET;
}
`,
config: {
env: {
MY_SECRET: "supersecretvalue",
},
},
});Network Security and proxying
By default, serverless runs have complete access to the internet. However, you can
restrict access using the networkPermissions field in the config. Permissions
are matched against domains. If you specify allow rules, only those rules will
be allowed, and all other requests will be blocked. If a request is blocked, the
request will throw an error.
import { freestyle } from "freestyle-sandboxes";
freestyle.serverless.runs.create({
code: `
export default async () => {
await fetch("https://not-example.com");
return "Hello from Serverless!";
}
`,
config: {
networkPermissions: [
{
action: "allow",
domain: "example.com",
behavior: "exact",
},
]
}
});If you want to deny specific domains while allowing all others, you can use the deny action.
import { freestyle } from "freestyle-sandboxes";
freestyle.serverless.runs.create({
code: `
export default async () => {
const err = await fetch("https://blocked-domain.com").catch(e => e.message);
return err;
}
`,
config: {
networkPermissions: [
{
action: "deny",
domain: "blocked-domain.com",
behavior: "exact",
},
]
}
});You can also proxy network requests through your own proxy server using the
proxy field. It's sometimes useful to also include custom headers, which will
be applied to all requests made inside the serverless run.
import { freestyle } from "freestyle-sandboxes";
freestyle.serverless.runs.create({
code: ``,
config: {
proxy: "http://my-proxy-server.com",
},
headers: {
"Proxy-Authorization": "Basic base64encodedcredentials"
}
});Listing Serverless Runs
import { freestyle } from "freestyle-sandboxes";
const { runs } = await freestyle.serverless.runs.list({
limit: 10,
});
console.log(runs);[
{
runId: "6cfcae22-f9a0-46d5-89bf-2b55eb1e6c14",
createdAt: "2025-11-07T21:58:48.511978Z",
startedAt?: "2025-11-07T21:58:48.536538Z",
status: "complete"
}
]You can paginate through serverless runs using the cursor field.
import { freestyle } from "freestyle-sandboxes";
let hasMore = true;
let nextCursor = undefined;
while (hasMore) {
const { runs, nextCursor: newCursor } = await freestyle.serverless.runs.list({
limit: 10,
cursor: nextCursor,
});
console.log(runs);
nextCursor = newCursor;
hasMore = !!nextCursor;
}