Services
Every Swisblade project is composed of one or more services. A service is either an application you build from source code (type: "app") or a pre-built Docker image (type: "custom").
App services
App services are built from your Git repository. Swisblade clones the repo, builds a Docker image, and runs it.
{
"api": {
"source": { "repo": "github.com/you/api.git", "ref": "main" },
"type": "app",
"runtime": "node",
"port": 3000,
"public": true,
"needs": ["postgres"]
}
}
Build process
- Swisblade clones your repository at the specified
ref(branch, tag, or commit SHA). - If a
Dockerfileexists at the repo root, it's used to build the image. - If there's no Dockerfile, Swisblade uses Nixpacks to auto-detect your tech stack and generate one.
Supported runtimes
| Runtime | runtime value | Auto-instrumentation |
|---|---|---|
| Node.js | "node" | OpenTelemetry for Express, Fastify, Hono, etc. |
| Python | "python" | OpenTelemetry for Flask, FastAPI, Django, etc. |
| Java | "java" | OpenTelemetry Java agent |
The runtime field enables automatic observability instrumentation. Your application sends traces and metrics without any code changes.
Monorepo / local source
If all your services live in a single repository, use source.path instead of source.repo:
{
"api": {
"source": { "path": "packages/api" },
"type": "app",
"runtime": "java",
"port": 3000
}
}
The path is relative to the project root. With local source, Swisblade skips the git clone step and builds directly from the specified directory. Each directory must contain its own Dockerfile or be auto-detectable by Nixpacks.
Versioning with ref
The ref field controls which version of your code gets deployed:
"source": { "repo": "github.com/you/api.git", "ref": "main" }
You can use:
- Branch names:
"main","develop"— deploys the latest commit on that branch. - Tags:
"v1.2.0","release-2024-01"— pins to a specific release. - Commit SHAs:
"a1b2c3d"— pins to an exact commit.
Use tags or commit SHAs for production deployments. Branch names deploy the latest commit, which may change between deploys.
Custom services
Custom services run pre-built Docker images. Use them for third-party tools, databases, or any service you don't build yourself.
{
"search": {
"type": "custom",
"image": "elasticsearch:8.12.0",
"port": 9200
}
}
| Field | Description |
|---|---|
image | Docker Hub image and tag (e.g., rabbitmq:3-management) |
port | The port the service listens on inside the container |
protocol | Protocol for generated URLs (default: "http", use "amqp" for message queues, etc.) |
Examples
RabbitMQ with management UI:
{
"mq": {
"type": "custom",
"image": "rabbitmq:3-management",
"protocol": "amqp",
"port": 5672
}
}
MongoDB:
{
"mongo": {
"type": "custom",
"image": "mongo:7",
"port": 27017
}
}
Database services
Database services declare named databases on the shared platform. They don't run containers — they provision a dedicated database and user on the existing PostgreSQL or MySQL instance.
{
"analytics-db": {
"type": "database",
"engine": "mysql"
}
}
App services connect to them via connects_to, which injects a DATABASE_URL_{NAME} environment variable with dedicated credentials. See Databases for details.
In the dashboard, database services show a Shared status badge (green) and appear in the network topology map with their own node.
Service connections
connects_to
When one service needs to talk to another, declare it in connects_to:
{
"api": {
"type": "app",
"connects_to": ["worker", "search"]
},
"worker": { "type": "app", "port": 8080 },
"search": { "type": "custom", "image": "elasticsearch:8.12.0", "port": 9200 }
}
The API service receives:
WORKER_URL=http://worker:8080SEARCH_URL=http://search:9200
needs
For managed databases and infrastructure, use needs instead. See Databases.
{
"api": {
"needs": ["postgres", "redis"]
}
}
The API service receives:
DATABASE_URL=postgresql://proj_xxx:password@platform-postgres:5432/proj_xxxREDIS_URL=redis://proj_xxx:password@platform-redis:6379/0REDIS_KEY_PREFIX=proj_xxx:
Networking
Services within the same project can communicate using their service names as hostnames (e.g., http://worker:8080). This works via Docker's internal DNS.
Services from different projects are isolated from each other — they cannot communicate directly.