Skip to content

Stateful Services

Skipper manages stateful services (databases, caches) separately from apps. Services use StatefulSets with persistent storage. They survive restarts and keep their data.

Adding a service

bash
kip service add postgres --name mydb
kip service add mysql --name mydb
kip service add mongodb --name mydb
kip service add redis --name cache
kip service add rabbitmq --name queue
kip service add opensearch --name search
kip service add minio --name storage

Supported types: postgres, mysql, mongodb, redis, rabbitmq, opensearch, minio

Per-environment services

Each environment can have its own database with separate credentials and storage:

bash
kip service add postgres --name db --project yourr-name --environment test --storage 1Gi
kip service add postgres --name db --project yourr-name --environment acc --storage 2Gi
kip service add postgres --name db --project yourr-name --environment prod --storage 10Gi

Each environment's database is fully isolated. Test data never touches production. Test and acc can use smaller storage allocations to save resources.

What this creates

Options

FlagDefaultDescription
--nameRequiredService name
--projectdefaultProject name
--environmentTarget environment (e.g. test, acc, prod)
--storage5Gi (postgres/mysql/mongodb/opensearch), 1Gi (redis/rabbitmq), 10Gi (minio)Storage size

Connection details

After creating a service, the connection details are displayed:

  Host:     mydb.default.svc.cluster.local
  Port:     5432
  Username: skipper
  Password: a1b2c3d4e5f6...
  Database: app

Retrieve them later:

bash
kip service info mydb

The hostname (mydb.default.svc.cluster.local) is a Kubernetes internal DNS name. Apps running on the same cluster can connect to it directly.

MinIO (S3-compatible object storage)

MinIO provides S3-compatible object storage for file uploads, media, documents, and other binary data.

bash
kip service add minio --name storage --project yourr-name --environment test
  Host:     storage.yourr-name-test.svc.cluster.local
  Port:     9000
  Username: skipper
  Password: a1b2c3d4e5f6...
  Endpoint: http://storage.yourr-name-test.svc.cluster.local:9000
  Console:  http://storage.yourr-name-test.svc.cluster.local:9001

Bind MinIO to your app to inject credentials automatically:

bash
kip service bind storage api --project yourr-name --environment test

This injects S3_HOST, S3_PORT, S3_USERNAME, and S3_PASSWORD into the app. Use them with any S3-compatible SDK (AWS SDK, MinIO SDK, boto3). See the Storage page for mc CLI examples and SDK code samples.

File explorer

MinIO services include a built-in file explorer in the web console. Navigate to Storage in the sidebar to browse buckets, upload and download files, delete objects, and generate share links (presigned URLs). See the Storage page for full details.

Connecting from your machine

Services run inside the cluster and are not exposed to the internet. To connect with a desktop database client (DBeaver, TablePlus, pgAdmin, RedisInsight, or any other tool), use kip tunnel to open a secure connection from your machine to the service:

bash
kip tunnel mydb
  ✔  Tunnel open: localhost:5432 → mydb (postgres)
  Press Ctrl+C to close

Open your database client and connect to localhost:5432 with the credentials from kip service info mydb.

If the default port is already in use on your machine, pick a different one:

bash
kip tunnel mydb --local-port 15432

For services in a specific environment:

bash
kip tunnel db --project yourr-name --environment staging

See Team Access for the full tunnel documentation, including Redis examples and troubleshooting.

Binding to apps

Bind a service to an app to inject connection details as environment variables:

bash
kip service bind db domain-service --project yourr-name --environment test

Per-app databases

For database services (PostgreSQL, MySQL, MongoDB), Skipper automatically creates a dedicated database for each app. The database name is derived from the app name and environment:

AppEnvironmentDatabase name
domain-servicetestdomain_service_test
identity-serviceprodidentity_service_prod
exchange-serviceaccexchange_service_acc
api(none)api

This means multiple microservices can share a single PostgreSQL instance while keeping their data completely isolated.

Injected environment variables

The binding injects individual connection components with a type-based prefix. The prefix depends on the service type:

Database services (PostgreSQL, MySQL, MongoDB), prefix DB_:

VariableExample value
DB_HOSTdb.yourr-name-test.svc.cluster.local
DB_PORT5432
DB_USERNAMEskipper
DB_PASSWORDa1b2c3d4e5f6...
DB_NAMEdomain_service_test

MinIO, prefix S3_:

VariableExample value
S3_HOSTstorage.yourr-name-test.svc.cluster.local
S3_PORT9000
S3_USERNAMEskipper
S3_PASSWORDa1b2c3d4e5f6...

Redis, prefix REDIS_. RabbitMQ, prefix AMQP_. OpenSearch, prefix OPENSEARCH_.

Your app constructs a connection URL from these components in whatever format your framework needs:

  • Node.js / Python / Ruby / Go: postgres://${DB_USERNAME}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_NAME}
  • Java / Spring Boot (JDBC): jdbc:postgresql://${DB_HOST}:${DB_PORT}/${DB_NAME}
  • S3 endpoint (MinIO): http://${S3_HOST}:${S3_PORT}

Unbinding

Remove a binding from the console (env tab → click X on the service) or the CLI:

bash
kip service unbind db domain-service --project yourr-name --environment test

Deleting a service automatically unbinds it from all apps. The per-app databases are not dropped. They remain in the PostgreSQL instance for manual cleanup if needed.

The app restarts automatically when a binding is added or removed.

Listing services

bash
kip service list
  NAME       TYPE         STATUS     READY      STORAGE
  mydb       postgres     running    1/1        5Gi
  cache      redis        running    1/1        1Gi

Services also appear in the web console under the Services sidebar item, where you can view connection details with a masked URL and copy-to-clipboard.

Deleting a service

Deleting a service permanently destroys all data. Skipper requires an explicit flag to prevent accidents:

bash
# This will be rejected
kip service delete mydb

# This works, data is permanently destroyed
kip service delete mydb --delete-data

DANGER

--delete-data is irreversible. The persistent volume and all data are permanently deleted. There is no undo.

Resource limits

Configure CPU and memory limits for your services from the Resources tab in the service detail panel. Click a service in the web console, switch to the Resources tab, and adjust the CPU and memory requests and limits.

Resource limits control how much CPU and memory the service pod is allowed to consume. Databases under heavy query load or caches handling high throughput may need higher limits than the defaults.

WARNING

Changing resource limits on a service triggers a pod restart. For databases (PostgreSQL, MySQL, MongoDB), this means a brief period of downtime while the pod restarts with the new limits. Plan resource changes during a maintenance window or low-traffic period.

How services differ from apps

AppsServices
Kubernetes resourceDeploymentStatefulSet
StorageNone (stateless)PersistentVolumeClaim
RestartRolling restart, safeWarns, requires --force
DeleteImmediateRequires --delete-data
Scalingkip app scaleSingle replica (MVP)
External accessVia Ingress (public URL)Internal only (cluster DNS)

Released under the Apache 2.0 License.