specific.hcl drives specific dev locally and specific deploy in production.
A typical setup with a public frontend and API:
specific.hcl
command- command to start the server.root- working directory for service commands, relative tospecific.hcl. Defaults to the referenced build’sroot, or"."if no build.endpoint- defines a network endpoint (see below).port- reference to the auto-assigned port; pass it to your server.
build block.
Endpoints
Endpoints define how a service is accessible over the network.Single endpoint
specific.hcl
public = truemakes the endpoint publicly accessible via HTTPS.- Omitting
public(orpublic = false) keeps the endpoint internal-only.
*.spcf.app URL by default. To attach your own domain, see Custom domains.
Multiple named endpoints
A service can expose multiple endpoints on different ports, each independently public or internal:specific.hcl
endpoint.<name>.port instead of port to reference each endpoint’s port.
Implicit endpoints
If a service usesport in its env vars but has no explicit endpoint blocks, an implicit internal endpoint is created:
specific.hcl
Health checks
Add ahealth_check block inside an endpoint to tell Specific how to verify the service is healthy. The platform sends an HTTP GET to the given path on the endpoint’s port; a 2xx response means healthy.
specific.hcl
path- the HTTP path to probe (required, must start with/).- Keep the handler cheap: don’t query the database or call other services. A constant
200 OKis sufficient. If your service already serves a root path that always returns2xx(for example, a static site), pointhealth_checkat/. - Only one
health_checkper service is used. If multiple endpoints declare one, the first one wins. - Background workers (services without endpoints) don’t support
health_checkyet - only HTTP-serving endpoints do.
- During a deploy, the new instance doesn’t receive traffic until its health check passes. The old version stays up until then, so users never hit a half-started process.
- If the health check starts failing after the deploy is live, the service is restarted automatically. Traffic is drained from the unhealthy instance before the restart.
- If the health check never passes during a deploy (typically a misconfigured
path), the deploy fails fast with ahealth_check_failederror pointing at the probe URL.
Connecting services
Private communication
Services reference each other’s endpoints withprivate_url to communicate over a private network:
specific.hcl
| Attribute | Description |
|---|---|
service.<name>.private_url | Internal URL without scheme (for example, localhost:3001 in dev). Only reachable by other services. |
service.<name>.host | Host only. |
service.<name>.port | Port only. |
service.<name>.public_url | Public URL without scheme (my-app.spcf.app in production, localhost:3001 in dev). Only available for endpoints with public = true. |
service.api.endpoint.main.private_url.
public_url and private_url do not include a scheme. Production services are served over HTTPS; local development uses plain HTTP. Compose the full URL with the right scheme per environment, using the dev block to override locally:Public communication
Private URLs aren’t reachable from a browser. When a frontend needs to call a backend, the backend must expose a public endpoint, and the frontend references it withpublic_url:
specific.hcl
Environment variables
All connection details (database URLs, storage credentials, secrets) are injected as environment variables. The same references resolve to the correct values in both local development and production.specific.hcl
String interpolation
Embed references inside strings to compose values:specific.hcl
Local development
Dev commands
Thedev block overrides how a service runs during specific dev. Use it for hot-reload servers, watch modes, or anything optimized for a fast feedback loop. If the referenced build has no dev block, the build step is skipped in development.
specific.hcl
dev.env block is merged with the top-level env, so you only override the variables that differ.
Dev-only services
A service with adev.command but no top-level command only runs in local development and is excluded from deployment. Useful for local versions of external services like mock servers:
specific.hcl
build reference, and can define endpoints that other services reference during development.
See Local development for ports, logs, isolated instances, and tunnels.
Monorepos
Useroot on builds to set the working directory. Services inherit the build’s root, so commands like npm start run from the correct directory:
specific.hcl
root.
Workers
Services without any endpoint act as background workers. They deploy like other services but don’t receive HTTP traffic, which is common for queue consumers and background processing.specific.hcl
Pre-existing images
Services can run a pre-built container image instead of a build.image and build are mutually exclusive, and image-based services skip the build step entirely:
specific.hcl
image- container image reference (for example,redis:7orghcr.io/org/image:tag).- Use
dev.commandto run the equivalent process locally. - Deploy hooks work with image-based services, and you can mix build-based and image-based services in one project.
Deploy hooks
Run commands before or after deploying a service. Hooks run as one-off jobs with the same container and environment variables as the service. If a hook fails, the deployment is aborted.specific.hcl
pre_deploy- runs before the service is deployed. Database migrations belong here: the schema is updated before new code runs, and a failed migration aborts the deployment instead of leaving a broken state.post_deploy- runs after the service is deployed (cache warming, notifications).
specific exec whenever the schema changes, for example specific exec api -- npm run db:push.
Graceful shutdown
When a service is redeployed or stopped, Specific sends your app aSIGTERM signal and waits a short grace period before forcibly stopping it. Handle SIGTERM to finish in-flight requests and close connections cleanly.
For the signal to reach your code, command should run your app as a process that receives signals. Running your server directly (node server.js, ./api) is the most reliable; wrappers and process managers can swallow the signal.
Serving static files
To serve static files, run a web server as a service. For example, withnpx serve:
specific.hcl