Sprintsail Developer Guide
Everything your team needs to ship production workloads on Sprintsail — from first push to scaled production. This guide covers authentication, deployment, services, domains, scaling, monitoring, CI/CD, and team management.
Audience: Engineers, DevOps, Platform Engineers, Technical Leads
1. Platform Overview
Sprintsail is a fully managed application PaaS. You push source code — we handle the build, deploy, TLS, DNS, scaling, and monitoring. Your code runs in your cloud account. We orchestrate it.
What you get:
- Source-to-production in under 60 seconds (
ss push) - 8 runtime support: Node.js, Python, Go, Rust, Java, .NET, Ruby, static sites
- Managed PostgreSQL, Redis, and S3 via service marketplace
- Automatic TLS certificates (Let's Encrypt)
- Custom domain mapping with DNS automation
- Horizontal and vertical autoscaling
- Integrated logging, metrics, and dashboards
- GitHub Actions / GitLab CI integration
- Team-based RBAC (organizations, spaces, roles)
What you don't manage:
- Kubernetes clusters, node groups, or control plane
- Load balancers, ingress controllers, or DNS records
- Certificate provisioning or renewal
- Container image registries or build pipelines
- Network policies, security groups, or WAF rules
2. Prerequisites
Install the CLI
npm install -g @sprintsail/cli
Verify installation:
ss version
Authenticate
ss login
This opens your browser for PKCE-based OAuth authentication via Cognito. The CLI starts a local callback server on localhost:9876, receives the authorization code, and exchanges it for tokens. Tokens are stored locally and refresh automatically.
# Verify your identity
ss whoami
Output:
Email: engineer@company.com
Org: acme-corp
Role: admin
Logout
ss logout
3. Organizations and Spaces
Organizations
An organization is your top-level account. All apps, services, and team members belong to an org.
# Create an org
ss org create acme-corp
# List your orgs
ss orgs
# Switch active org
ss org set acme-corp
Org approval: New organizations require admin approval before they can deploy workloads. You'll receive an email once approved.
Spaces
Spaces isolate workloads within an org. Use them for environments (production, staging, dev) or team boundaries.
# Create a space
ss space create production
ss space create staging
# List spaces
ss spaces
# Set active space
ss space set production
Each space maps to a Kubernetes namespace (sprintsail-{org}-{space}) with its own resource quotas and network policies.
Team Roles
| Role | Permissions |
|---|---|
| owner | Full control. Billing, member management, delete org. |
| admin | Manage apps, services, spaces, members. Cannot delete org or manage billing. |
| member | Deploy apps, bind services, view logs. Cannot manage team or spaces. |
Org owners and admins implicitly have space-level manager access.
4. Deploying Applications
Method 1: Source Push (Recommended)
Push your source code directly. Sprintsail detects the runtime and builds with Cloud Native Buildpacks (Paketo).
# Navigate to your project root
cd my-app
# Create the app
ss create my-api
# Deploy
ss push
What happens on ss push:
- Upload — Source code is packaged and uploaded to S3 (encrypted at rest, 30-day lifecycle)
- Detect — Paketo buildpacks detect the runtime (Node.js, Python, Go, etc.)
- Build — CodeBuild compiles a production OCI image using the detected buildpack
- Push — Image is pushed to your org's ECR repository
- Deploy — A Kubernetes Deployment is created with health checks, resource limits, and a ClusterIP Service
- Route — An Ingress rule is configured with TLS termination and DNS record
- Live — Your app is reachable at
{app-name}.sprintsail.com
Supported runtimes:
| Runtime | Detection | Build |
|---|---|---|
| Node.js | package.json | npm/yarn install, production prune |
| Python | requirements.txt or Pipfile | pip install, gunicorn |
| Go | go.mod | go build, static binary |
| Rust | Cargo.toml | cargo build --release |
| Java | pom.xml or build.gradle | Maven/Gradle build, JVM optimization |
| .NET | *.csproj or *.sln | dotnet publish |
| Ruby | Gemfile | bundle install, puma |
| Static Sites | index.html or build output | NGINX serve |
Method 2: Dockerfile
If your app has a Dockerfile in the root, Sprintsail uses it instead of buildpacks.
FROM node:22-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --production
COPY . .
USER 1000:1000
EXPOSE 8080
CMD ["node", "server.js"]
Requirements:
- Must expose a port (default: 8080, configurable via
ss env set PORT=3000) - Must run as non-root user (enforced by admission policy)
- Image must not use
:latesttag (enforced by OPA Gatekeeper)
Method 3: Pre-built Image
Deploy an existing container image from any approved registry:
ss create my-app --image {account}.dkr.ecr.{region}.amazonaws.com/my-app:v1.2.3
Approved registries:
- Your account's ECR (
{account}.dkr.ecr.{region}.amazonaws.com/) - Paketo buildpack images (
paketobuildpacks/,gcr.io/paketo-buildpacks/)
Other registries are blocked by admission policy.
Application Lifecycle
# List all apps in the current space
ss apps
# Get detailed info
ss info my-api
# Stop an app (scale to 0)
ss stop my-api
# Start a stopped app
ss start my-api
# Restart (rolling restart, no downtime)
ss restart my-api
# Delete an app and all its resources
ss delete my-api
5. Environment Variables
Setting Variables
# Set a single variable
ss env set my-api DATABASE_URL=postgres://...
# Set multiple variables
ss env set my-api NODE_ENV=production LOG_LEVEL=info
# View current variables
ss env my-api
Environment variables are injected into the container at runtime via Kubernetes ConfigMaps. Changes trigger a rolling restart.
Secrets
For sensitive values (API keys, passwords, connection strings), use the secrets command:
# Set a secret (stored in Kubernetes Secrets, not ConfigMaps)
ss env set my-api --secret STRIPE_KEY=sk_live_xxxxxxxxxxxx
# Secrets are masked in output
ss env my-api
# STRIPE_KEY=****
Secrets are encrypted at rest via Kubernetes secrets encryption (AWS KMS backed).
Reserved Variables
These are set automatically by Sprintsail:
| Variable | Value |
|---|---|
PORT | The port your app should listen on (default: 8080) |
SPRINTSAIL_APP | Your app name |
SPRINTSAIL_SPACE | Current space name |
SPRINTSAIL_ORG | Current org slug |
6. Service Marketplace
Sprintsail provisions managed infrastructure services and injects connection details into your app automatically.
Available Services
| Service | Backing | Plans |
|---|---|---|
| PostgreSQL | AWS RDS PostgreSQL 16 | micro (t4g.micro, 20GB), small (t4g.small, 50GB) |
| Redis | AWS ElastiCache Redis 7.1 | micro (t4g.micro) |
| Object Storage | AWS S3 | standard (versioning optional) |
# Browse the marketplace
ss marketplace
Create a Service Instance
# Provision a PostgreSQL database
ss create-service postgresql micro my-db
# Provision Redis
ss create-service redis micro my-cache
# Provision S3 storage
ss create-service storage standard my-bucket
Service provisioning is asynchronous — Crossplane creates the underlying AWS resource. Typical provisioning time:
- PostgreSQL: 3-5 minutes
- Redis: 2-3 minutes
- S3: 30 seconds
Bind a Service to an App
ss bind-service my-api my-db
Binding injects connection details as environment variables:
PostgreSQL binding:
DATABASE_HOST=<auto-generated-endpoint>
DATABASE_PORT=5432
DATABASE_NAME=app_db
DATABASE_USER=app_user
DATABASE_PASSWORD=<auto-generated>
DATABASE_URL=postgres://app_user:****@host:5432/app_db?sslmode=require
Redis binding:
REDIS_HOST=<auto-generated-endpoint>
REDIS_PORT=6379
REDIS_URL=redis://host:6379
S3 binding:
S3_BUCKET=<auto-generated-bucket>
S3_REGION=<your-region>
AWS_ACCESS_KEY_ID=<scoped credentials>
AWS_SECRET_ACCESS_KEY=<scoped credentials>
View and Unbind Services
# List services in current space
ss services
# Unbind a service from an app
ss unbind-service my-api my-db
Unbinding removes the environment variables and triggers a rolling restart. It does not delete the service instance or its data.
7. Custom Domains
Map a Domain
ss map-domain my-api app.company.com
Sprintsail automatically:
- Creates a DNS CNAME record pointing to the ingress load balancer
- Provisions a TLS certificate via Let's Encrypt (DNS-01 challenge)
- Configures the ingress rule for host-based routing
DNS Configuration
Add a CNAME record at your DNS provider:
app.company.com CNAME ingress.sprintsail.com
For apex domains (e.g., company.com), use an ALIAS or ANAME record if your provider supports it.
Verify Domain Status
ss domains my-api
Output:
DOMAIN STATUS TLS
my-api.sprintsail.com active valid (expires 2026-07-18)
app.company.com active valid (expires 2026-07-18)
Remove a Domain
ss unmap-domain my-api app.company.com
8. Scaling
Manual Scaling
# Scale to 3 instances
ss scale my-api --instances 3
# Scale resources
ss scale my-api --memory 512Mi --cpu 500m
Autoscaling
# Enable autoscaling (2 to 10 instances, target 70% CPU)
ss autoscale my-api --min 2 --max 10 --cpu-target 70
Autoscaling creates a Kubernetes HorizontalPodAutoscaler. Your app scales based on CPU utilization, with a 60-second stabilization window.
Default resource allocations:
| Size | CPU Request | CPU Limit | Memory Request | Memory Limit |
|---|---|---|---|---|
| micro | 100m | 250m | 128Mi | 256Mi |
| small | 250m | 500m | 256Mi | 512Mi |
| medium | 500m | 1000m | 512Mi | 1Gi |
| large | 1000m | 2000m | 1Gi | 2Gi |
Zero-Downtime Deployments
All deployments use Kubernetes rolling updates:
maxUnavailable: 0— no downtime during deploysmaxSurge: 25%— temporary extra capacity during rollout- Health checks gate traffic — new pods only receive traffic after passing readiness probes
9. Deployments and Rollbacks
View Deployment History
ss deployments my-api
Output:
VERSION STATUS IMAGE CREATED
v5 active my-api:abc123 2 hours ago
v4 inactive my-api:def456 1 day ago
v3 inactive my-api:ghi789 3 days ago
Rollback
# Rollback to the previous version
ss rollback my-api
# Rollback to a specific version
ss rollback my-api --version v3
Rollbacks are instant — they repoint the Deployment to a previous image digest. No rebuild required.
10. Logs and Monitoring
Application Logs
# Stream live logs
ss logs my-api
# View recent logs (last 100 lines)
ss logs my-api --recent
# Follow logs from all instances
ss logs my-api --follow
Logs are collected via Loki and retained for 15 days. They're also shipped to CloudWatch Logs under /sprintsail/apps/{org}/{space}/{app}.
Metrics and Dashboards
Every app automatically exposes:
- CPU utilization — per-pod and aggregate
- Memory usage — working set vs limits
- Request rate — requests per second at the ingress
- Response latency — p50, p95, p99 at the ingress
- Error rate — 4xx and 5xx responses
Access Grafana dashboards at your org's monitoring endpoint (provided after org approval).
Health Checks
Sprintsail configures health checks automatically:
| Probe | Path | Interval | Threshold |
|---|---|---|---|
| Readiness | GET / (or custom) | 10s | 3 failures → stop traffic |
| Liveness | GET / (or custom) | 30s | 3 failures → restart pod |
Customize health check paths:
ss env set my-api HEALTH_CHECK_PATH=/healthz
11. CI/CD Integration
GitHub Actions
name: Deploy to Sprintsail
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Sprintsail CLI
run: npm install -g @sprintsail/cli
- name: Authenticate
run: ss login --token ${{ secrets.SPRINTSAIL_TOKEN }}
- name: Set target
run: |
ss org set ${{ vars.SS_ORG }}
ss space set production
- name: Deploy
run: ss push
GitLab CI
deploy:
stage: deploy
image: node:22
script:
- npm install -g @sprintsail/cli
- ss login --token $SPRINTSAIL_TOKEN
- ss org set $SS_ORG
- ss space set production
- ss push
only:
- main
Webhook Deployments
Sprintsail exposes a webhook endpoint for custom CI systems:
curl -X POST https://api.sprintsail.com/api/v1/webhooks/deploy \
-H "Authorization: Bearer $SPRINTSAIL_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"app": "my-api",
"org": "acme-corp",
"space": "production",
"image": "{account}.dkr.ecr.{region}.amazonaws.com/my-api:v1.2.3"
}'
12. CLI Reference (Quick)
| Command | Description |
|---|---|
ss login | Authenticate via browser (PKCE flow) |
ss logout | Clear stored tokens |
ss whoami | Show current identity and org |
ss orgs | List organizations |
ss org create <name> | Create a new organization |
ss org set <name> | Switch active organization |
ss spaces | List spaces in current org |
ss space create <name> | Create a space |
ss space set <name> | Switch active space |
ss create <app> | Create a new application |
ss push | Build and deploy current directory |
ss apps | List apps in current space |
ss info <app> | Show app details |
ss logs <app> | Stream application logs |
ss scale <app> | Scale instances or resources |
ss autoscale <app> | Configure horizontal autoscaling |
ss env <app> | List environment variables |
ss env set <app> KEY=VAL | Set environment variable |
ss marketplace | Browse available services |
ss create-service <type> <plan> <name> | Provision a service |
ss bind-service <app> <svc> | Bind service to app |
ss services | List service instances |
ss domains <app> | List mapped domains |
ss map-domain <app> <domain> | Map custom domain |
ss deployments <app> | View deployment history |
ss rollback <app> | Rollback to previous version |
ss stop <app> | Scale to zero |
ss start <app> | Resume a stopped app |
ss restart <app> | Rolling restart |
ss delete <app> | Delete app and resources |
For the full CLI reference, see CLI Reference.
13. API Reference (Quick)
All API endpoints are available at https://api.sprintsail.com/api/v1/.
Authentication: Authorization: Bearer <id_token>
| Method | Endpoint | Description |
|---|---|---|
| GET | /orgs | List your organizations |
| POST | /orgs | Create organization |
| GET | /orgs/:slug/spaces | List spaces |
| POST | /orgs/:slug/spaces | Create space |
| GET | /orgs/:slug/spaces/:name/apps | List apps |
| POST | /orgs/:slug/spaces/:name/apps | Create app |
| POST | /orgs/:slug/spaces/:name/apps/:app/deploy | Deploy app |
| GET | /orgs/:slug/spaces/:name/apps/:app/logs | Stream logs (WebSocket) |
| PUT | /orgs/:slug/spaces/:name/apps/:app/scale | Scale app |
| GET | /orgs/:slug/spaces/:name/services | List services |
| POST | /orgs/:slug/spaces/:name/services | Create service |
| POST | /orgs/:slug/spaces/:name/services/:svc/bind | Bind to app |
For the full API reference, see API Reference.
14. Troubleshooting
Build Failures
"No buildpack detected"
- Ensure your project has the correct detection file (
package.json,requirements.txt,go.mod, etc.) in the root directory - If using a monorepo, set the build context:
ss env set my-api BUILD_PATH=./services/api
"Build timed out"
- Default build timeout is 15 minutes
- Large dependency installs (Java, .NET) may need more time — contact support
Deployment Failures
"CrashLoopBackOff"
- Your app is crashing on startup. Check logs:
ss logs my-api --recent - Common causes: missing environment variables, incorrect PORT, database not reachable
"ImagePullBackOff"
- The container image couldn't be pulled. Verify the image exists and the registry is approved
"OOMKilled"
- Your app exceeded its memory limit. Scale up:
ss scale my-api --memory 512Mi
Service Binding Failures
"Service not ready"
- Database provisioning takes 3-5 minutes. Wait and retry:
ss servicesto check status - If stuck in "provisioning" for more than 10 minutes, contact support
DNS/TLS Issues
"Certificate pending"
- DNS propagation can take up to 5 minutes. Verify your CNAME record is correct
- If using Cloudflare, ensure proxy is disabled (DNS-only mode) for the CNAME
15. Limits and Quotas
| Resource | Default Limit | Adjustable |
|---|---|---|
| Apps per space | 25 | Yes |
| Instances per app | 10 | Yes |
| CPU per instance | 2 vCPU | Yes |
| Memory per instance | 2 GiB | Yes |
| Service instances per space | 10 | Yes |
| Custom domains per app | 5 | Yes |
| Build timeout | 15 minutes | No |
| Source upload size | 500 MB | No |
| Environment variables per app | 100 | No |
| Log retention | 15 days | No |
Limits are enforced via Kubernetes ResourceQuotas and LimitRanges at the namespace level.
Next Steps
- Architecture — Understand how the platform works under the hood
- Plans and Pricing — Compare Starter, Growth, and Enterprise plans
- Support — Email support@sprintsail.com or reach out via the dashboard