Run a Node web service that scales to zero
· the plori team
Ask a plori agent to build and test a small Node HTTP service in the Workspace files.
After you review and activate it, the service gets its own plori.site address. The
first request boots an isolated container; after a short idle window, that container
stops and runtime billing stops with it.
The source directory is part of the Workspace files, which persist between runs. Each activation or redeploy takes a snapshot of that directory for the service container. Editing the source does not change the live service until you redeploy it.
One service, through its full lifecycle
The owner activates the tested app, then verifies cold wake, idle sleep, snapshot isolation, redeploy, and runtime billing.
- 01
Build
Server + manifest
Tested on disk
- 02
Activate
Owner reviews first
Public or private
- 03
Wake + sleep
Request, then idle
Scale to zero
- 04
Redeploy
Snapshot v2
Next request boots
What do you need?
- A registered plori account and a Workspace.
- A server that listens on
process.env.PORTor the port declared inplori-service.json. - A globally unique name for the service's
<name>.plori.siteaddress. - Enough credits for the service's runtime. A service costs $0.01 per minute, billed by the second while its container is running, including the short idle window before it sleeps. It uses no runtime credits while asleep.
This example uses only Node's built-in http module. It needs no package install,
database, secret, or external service.
What prompt should you give plori?
This is the prompt used to build the production test service. Its paths now name the
Workspace directory /workspace/app, because only files under /workspace are kept
between runs. It asks the agent to stop
after handing you a ready-to-activate card because activation makes the endpoint
reachable and starts runtime billing.
Create a minimal dependency-free Node HTTP service in /workspace/app. Write /workspace/app/server.js so it listens on process.env.PORT || 3000 and returns JSON with exactly {"ok":true,"version":"v1","message":"plori scale-to-zero service"} for every request. Write /workspace/app/plori-service.json with start "node server.js" and port 3000.
Test the service locally on an available port, confirm the exact response, and stop the test process. Do not publish or activate it yourself. When the files and local test are complete, use the product's ready-to-activate handoff for that app directory as a Service so I can review and activate it in the UI. Do not add dependencies, databases, external services, secrets, or background processes.What does the agent create?
The app directory contains the server and a small service manifest:
{
"start": "node server.js",
"port": 3000
}
start is the command the service container runs from the app directory. port must be
between 1024 and 65535, and the server must listen on it. The manifest can also declare
non-secret environment values and snapshot exclusions. Do not put API keys or other
secrets in the manifest; it is a file in the Workspace.
The agent tests the process before handoff and then stops it. A successful local test shows that the code can answer on the declared interface. It does not publish the app or prove the production cold-start path.
How do you activate the service?
- Open the Ready to activate card in the agent conversation.
- Check that the app directory is
/app(the Workspace'sappdirectory) and the publish mode is Service. - Choose Private or Public. Private is the safer default while you test.
- Click Activate service. Activation is always an owner action; the agent cannot do it for you.
- Open the service. The first request boots the container and may include a brief cold start. The owner page changes from Asleep to Running.
You can reach the same dialog from Files: open plori-service.json, click Publish
as a website, and keep Service selected. The full UI path is in
Publish a site.
What did the production run prove?
On 30 August 2026, we ran this lifecycle against production with a dedicated test agent. The owner activated a public service, verified the v1 JSON response, left it without traffic for more than 140 seconds, and saw the owner status change to Asleep. The next request returned HTTP 200 with the same body in 2.888 seconds and changed the status to Running.
We then changed the source response from v1 to v2 in the Workspace files. Before redeploy, the public endpoint still returned v1. After the owner clicked Redeploy, the service returned the exact v2 JSON on its next request in 2.708 seconds:
{ "ok": true, "version": "v2", "message": "snapshot redeploy works" }
The service's own ledger references recorded ten $0.01 runtime charges, totaling $0.10 across two v1 runs and the redeployed v2 run. Those entries show that live service usage reached the owner-visible ledger; they are not a forecast for a different app or traffic pattern.
Why did the endpoint keep serving v1 after the source changed?
A service runs a deployed snapshot, not the live Workspace files. This keeps the running app separate from files the agent may still be editing. It also gives you a clear release point:
- Change and test the source in the Workspace files.
- Open Site settings and click Redeploy.
- The current container stops.
- The next request boots a new container from the new snapshot.
If a change must not reach users yet, leave it in the Workspace and do not redeploy. Switching a service between public and private changes access immediately, but it does not create a new code snapshot.
What persists when the service sleeps?
The source files in the Workspace persist. The running service container does not. Files that the server writes inside its own container disappear when that container is replaced or scaled to zero. Use an external database or object store when application data must survive restarts.
The current service shape is deliberately small:
- scale-to-zero only; there is no always-on setting;
- one
plori.siteaddress per agent, backed by either a static site or a service; - no managed database, cache, custom domain, or buildpack;
- a brief cold start on the first request after sleep;
- runtime at $0.01 per minute, billed by the second while the container is live, including its idle window.
For a browser-only page, use a static site instead. A static site serves the files as they were when you published, so publish again to update it. It keeps serving while the agent sleeps and has no service-runtime charge.
How do you verify your own service safely?
Use a versioned response or health endpoint, then check each boundary separately:
- Test the server locally and stop the test process.
- Activate it privately first and verify the exact response.
- Wait for the owner page to show Asleep, then request it again and confirm a cold wake.
- Change the version in the source files and confirm the endpoint still serves the old snapshot.
- Redeploy, request it again, and confirm the new version.
- Open Dashboard → Billing and look for
Serviceentries. - Deactivate the service when the test is over.
The credits guide explains the shared balance and ledger. See pricing for the current plans and other usage rates.
When should you deactivate it?
Deactivate a test endpoint as soon as you finish. Open Site settings and click Deactivate. The URL stops serving, and the reserved name stays attached to that agent. Deleting the Workspace also removes its source files, so download anything you need first.
Related
- Publish a site, including private access, manifest fields, visibility, and service settings
- Disk and files, for the files a Workspace keeps
- What a credit buys, for the owner-visible billing ledger
- AI agent hosting, for the broader managed-agent model
Build it in plori
Open a plori agent and paste the prompt. Review the generated server and manifest, then activate the service yourself from the ready card.
Review the prompt before sending.