Skip to main content

Serverless guide

This is the end-to-end walkthrough for the Serverless service. It assumes nothing except that you have an account and a project, and it takes you from zero to a running, callable, auto-scaling service.

What Serverless is

Serverless runs your container — any image that speaks HTTP — and scales the number of running copies up and down with traffic, including all the way to zero when nobody is calling. Use it for public APIs, webhooks, internal services, scheduled jobs, and event handlers you do not want to babysit.

Use cases:

  • Public REST or gRPC API you want automatically load-balanced and HTTPS-terminated.
  • Webhook receiver that must wake on demand and sleep when quiet.
  • Nightly or cron-triggered job that should not pay for idle time.
  • Backend for an agent — a tool the agent invokes over HTTPS.

Quick start: working service in five commands

You need a container image in a registry the platform can reach. The example uses a tiny public "hello world" web server so nothing private is involved — substitute your own image reference here.

# 1. sign in once
platformctl login

# 2. create the service
platformctl serverless create hello --image ghcr.io/example/helloworld:latest

# 3. watch it come up
platformctl serverless get hello

# 4. publish a public HTTPS endpoint
platformctl serverless update hello --publish

# 5. call it
curl "$(platformctl serverless get hello -o json | jq -r .url)"

That is the whole loop. The same flow in the Console is Compute → Serverless → Create service → Publish.

Core concepts

  • A service is the named object you deploy and call. Its URL is stable across revisions.
  • A revision is one immutable version of the service — image, environment, limits. Every change creates a new revision.
  • Min scale keeps N copies warm. Max scale caps how far it can grow. Both are service-level settings.
  • Scale to zero happens when there is no traffic and min scale is 0. First request after idle pays a cold start.
  • A trigger is a scheduled (cron) or Pub/Sub-subscribed invocation that calls your service without a public URL.
  • A published service has a public HTTPS DNS name. An unpublished one is reachable only inside your project.
  • Timeout (seconds) bounds a single request. Long-running work should be split or use a higher timeout.
  • Environment variables can come from Secrets — you reference the secret by name and never paste the value.
  • Logs and metrics are per-service and streamable from the CLI or Console without setting up anything.
  • Every mutating call (create, patch, delete) is asynchronous; the service reports ready when the revision is serving.

API examples

The API is REST, bearer-token authenticated. The base is https://api.codyhill.dev and every path is project-scoped.

export API="https://api.codyhill.dev"
export PROJ="$(platformctl projects list -o json | jq -r '.[0].id')"
export TOK="<your session token or API key>"

Create a service:

curl -sX POST "$API/v1/projects/$PROJ/services" \
-H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' \
-d '{"name":"hello","image":"ghcr.io/example/helloworld:latest","publish":{"enabled":true}}'

Fetch its status and URL:

curl -s "$API/v1/projects/$PROJ/services/hello" -H "Authorization: Bearer $TOK"

Roll out a new revision (new image tag) and watch the revision list:

curl -sX PATCH "$API/v1/projects/$PROJ/services/hello" \
-H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' \
-d '{"image":"ghcr.io/example/helloworld:v2"}'

curl -s "$API/v1/projects/$PROJ/services/hello/revisions" -H "Authorization: Bearer $TOK"

Stream recent logs:

curl -s "$API/v1/projects/$PROJ/services/hello/logs?tail=200" -H "Authorization: Bearer $TOK"

CLI examples

platformctl serverless list # all services in the project
platformctl serverless get hello # status, URL, image, limits
platformctl serverless get hello -o json # machine-readable
platformctl serverless update hello --min-scale 1 # keep one copy warm
platformctl serverless update hello --timeout 600 # raise per-request timeout
platformctl serverless logs hello --tail 100 # recent logs
platformctl serverless metrics hello # current CPU, memory, RPS
platformctl serverless revisions hello # revision history
platformctl serverless delete hello # remove and release the URL

Console walkthrough

  1. Open the Console, pick your project.
  2. In the navigation, go to Compute → Serverless.
  3. Click Create service. Fill in a name, your image reference, and whether to Publish (public HTTPS endpoint).
  4. When the row in the list flips to Ready, click the service name to open its detail page.
  5. On the detail page: the URL is at the top, Revisions and Logs are tabs on the left, and Metrics are on the right.
  6. Click Edit to change image, environment, limits, or publish state. Every save rolls a new revision.
  7. To stop paying for cold copies, set Min scale to 0. To prevent a burst from running away, set Max scale.

Limits and quotas

The Serverless service enforces these defaults at the API:

SettingDefaultHard cap
Per-request timeout300 s3600 s (configurable per service)
Min scale0 (scale to zero)100
Max scale101000
CPU per instance1 vCPU4 vCPU
Memory per instance512 MiB8 GiB
Concurrent requests per instance1001000
Revision history keptlast 20revisions older than that are pruned

A request that exceeds the timeout is terminated with 504. Larger values require a quota change — open a support request from the Console.

Troubleshooting snippets

SymptomFirst thing to check
ImagePullBackOff on deployThe image reference is wrong, private, or the registry credential is missing. See troubleshooting.
Cold-start feels slowYour image takes too long to bind to the port. Keep startup under ~10 s or raise min-scale to keep one copy warm.
504 Gateway timeoutRequest exceeded the per-request timeout. Raise --timeout or split the work.
Logs show nothingThe service has not been hit yet, or logs are still flushing. platformctl serverless logs hello --tail 200 after a real request.
Connection refused from another serviceThe target is unpublished. Unpublished services are reachable only on their private, in-project address.
Public URL stopped resolvingThe --publish flag was cleared or the service was deleted. Re-create or re-publish.
High unhandled RPSConcurrency per instance is throttled. Lower max scale cost by raising the per-instance concurrency, or paginate at the client.

Security notes

  • Published services are public HTTP. Put authentication at the edge of your app code, or use a Gateway policy to require a token.
  • Environment values from Secrets are injected at run time and never appear in the API response. You reference the secret by name (see Secrets Manager).
  • Image supply chain: pin images by digest when the source matters, because the platform pulls what you reference at revision-roll time.
  • Inter-service traffic inside a project uses mutual TLS. A private (unpublished) service is not reachable from outside your project boundary.
  • Revision history is immutable. Sensitive values baked into a prior image layer or environment are still reachable from the revision list; only delete the service to fully release them.
  • The API is audited. Both the Console and platformctl use the same project-scoped role checks that govern who can deploy, publish, or delete.

Where next