Services
A Sprite pauses when nothing is using it, and processes don’t reliably survive the trip. A warm wake resumes them where they left off; a cold boot drops them entirely. Anything you started by hand in a shell, a dev server, a database, an agent, is gone after a cold wake unless something brings it back.
That something is a service. A service is a process the Sprite runtime owns: it starts when the Sprite boots, restarts if it crashes, and can receive the HTTP traffic that hits your Sprite’s URL. You define it once. The runtime keeps bringing it back.
Services and the Sprite lifecycle
Section titled “Services and the Sprite lifecycle”What happens to a service depends on how the Sprite went down and how it came back:
- Warm wake. The VM was suspended with your process inside it. The process resumes mid-thought; it is not restarted. Wakes take 100–500ms.
- Cold boot. Process state was dropped. The runtime starts every service fresh, in dependency order. Wakes take 1–2s.
- Crash. A service process that exits on its own gets restarted by the runtime.
- Stop. A service you stop explicitly stays stopped until you start it again.
Services don’t keep a Sprite from pausing. A Sprite with ten services defined still pauses when it goes idle; the services come back on the next wake. A service that’s actively handling HTTP requests counts as activity, the same as any other traffic, but a quiet one doesn’t hold the Sprite in an active state. If you need a Sprite to stay up while work finishes, that’s a job for the Tasks API, not a service.
Create a service
Section titled “Create a service”The sprite-env CLI ships in every Sprite and talks to the runtime’s management socket. Create a service with a name, a command, and its arguments:
sprite-env services create web --cmd python3 --args "-m,http.server,3000" --http-port 3000--cmd takes the binary only. Arguments go in --args, comma-separated.
The command starts the service and streams its first few seconds of output as NDJSON, so a service that dies on startup fails in front of you instead of silently in the background:
{"type":"started","timestamp":1780420274555}{"type":"complete","log_files":{"combined":"/.sprite/logs/services/web.log","stderr":"/.sprite/logs/services/web.log","stdout":"/.sprite/logs/services/web.log"},"timestamp":1780420276551}The stream watches for 5 seconds by default. Pass --duration 30s to watch longer, or --no-stream to return immediately.
Confirm it’s serving:
curl localhost:3000Create options
Section titled “Create options”| Flag | What it does |
|---|---|
--cmd <path> | The executable to run. Required. Binary only, no arguments here. |
--args <a,b,c> | Comma-separated arguments: --args "-m,http.server,3000" |
--env <K=v,...> | Comma-separated environment variables: --env "PORT=3000,DEBUG=1" |
--dir <path> | Working directory for the process |
--needs <svc,...> | Services that must start before this one |
--http-port <port> | Route the Sprite’s URL to this port and auto-start the service on incoming requests |
--duration <time> | How long to stream logs after starting (default: 5s) |
--no-stream | Don’t stream logs after creation |
Serving HTTP
Section titled “Serving HTTP”Every Sprite has a URL, and the Sprite’s proxy routes incoming requests to port 8080 by default. A service created with --http-port changes that:
- Requests to the Sprite’s URL route to the service’s port instead of 8080.
- If the service isn’t running when a request arrives, the proxy starts it first, then forwards the request.
- Only one service can have an HTTP port. Creating a second one fails with
409: another service already has an HTTP port configured.
Combined with wake-on-request, this gives you a server that costs nothing while idle. A request to a cold Sprite wakes the VM (1–2s), the proxy starts your service, and the request gets served. No traffic, no compute bill.
sprite-env services create web --cmd python3 --args "-m,http.server,3000" --http-port 3000The Sprite’s URL requires authentication by default. See Working with Sprites for URL auth modes and testing from outside the Sprite.
A Sprite URL can be switched to public access. Treat every HTTP service as potentially internet-facing: don’t serve secrets, environment variables, or unrestricted filesystem access.
Managing services
Section titled “Managing services”sprite-env services list # all services and their statesprite-env services get web # one servicesprite-env services restart web # stop, then start; streams logssprite-env services stop web # stop; stays stoppedsprite-env services start web # start a stopped servicesprite-env services signal web HUP # send any Unix signalsprite-env services delete web # remove the serviceget returns the definition plus live state:
{ "name": "web", "cmd": "python3", "args": ["-m", "http.server", "3000"], "http_port": 3000, "state": { "name": "web", "status": "running", "pid": 7353, "started_at": "2026-06-02T17:11:14.555839485Z" }}Three behaviors worth knowing:
stopis sticky. A stopped service stays stopped. The runtime won’t restart it behind your back.- Killing the process is not. Send
TERMorKILLviasignal, or kill the PID directly, and the runtime treats it as a crash and restarts the service. The state’srestart_countincrements each time. This meanssignal web TERMis effectively a restart; for clarity, userestartinstead. deleteremoves the definition, not the logs. The log file stays in/.sprite/logs/services/after the service is gone.
Everything a service writes to stdout or stderr lands in /.sprite/logs/services/<name>.log, timestamped and tagged with the stream it came from:
2026-06-02T17:11:17.821Z [stderr] 127.0.0.1 - - [02/Jun/2026 17:11:17] "GET / HTTP/1.1" 200 -Follow it like any other file:
tail -f /.sprite/logs/services/web.logTo watch output live while a service starts, use --duration on create, start, or restart.
There is no journalctl here. Sprites don’t run systemd; the log files and the create/start streams are how you see service output.
Dependencies
Section titled “Dependencies”A service with --needs starts after the services it names. Use it when one process can’t come up until another is ready:
# The database starts firstsprite-env services create postgres \ --cmd /usr/lib/postgresql/16/bin/postgres \ --args "-D,/home/sprite/pgdata"
# The app starts after postgressprite-env services create app \ --cmd npm --args "start" \ --dir /home/sprite/myapp \ --needs postgresOn a cold boot, the runtime starts postgres before app, every time.
Services, sessions, or tasks?
Section titled “Services, sessions, or tasks?”There are three ways to run something in a Sprite, and they solve different problems:
| Service | Session (sprite exec) | Task | |
|---|---|---|---|
| Survives a cold boot | Yes, restarts automatically | No | No, it’s a hold, not a process |
| Keeps the Sprite in an active state | Only while handling traffic | Yes, while producing output | Yes, until it expires |
| Best for | Servers, databases, daemons | Interactive work, builds, debugging | Holding the Sprite up while an agent or worker finishes |
They compose. A common pattern for background agents: a service launches the agent at boot, the agent registers a task while it works, the task expires when the work is done, and the Sprite pauses until something needs it again. See Keeping a Sprite Running for the task side of that pattern.
Troubleshooting
Section titled “Troubleshooting”The service died immediately.
The create stream tells you, with an exit event:
{"type":"started","timestamp":1780420024883}{"type":"exit","exit_code":1,"timestamp":1780420025035}Check the log file for the reason:
cat /.sprite/logs/services/web.logA bad --cmd path looks like this:
2026-06-02T17:07:38.805Z [stderr] executable file `/usr/bin/does-not-exist` not found: No such file or directoryThe service keeps restarting.
The runtime restarts crashing services, so a crash loop shows up as a climbing restart_count in sprite-env services get <name>. Read the log file to find out why it’s crashing, and test the command by hand in a shell with the same --dir and --env.
Requests to the Sprite’s URL aren’t reaching the service.
Check that the service actually has the HTTP port: sprite-env services list and look for http_port. Without it, the proxy routes to port 8080, not to your service.
Managing services from outside the Sprite
Section titled “Managing services from outside the Sprite”Everything on this page uses the in-Sprite CLI. The same operations are available from outside through the Sprites REST API at /v1/sprites/{name}/services and the SDKs, which is how you’d configure services as part of provisioning a fleet of Sprites. See the Services API reference for endpoints and request schemas.