Skip to Content
GuidesManaging Addons

Managing Addons

An addon is a Helm chart-based backing service: a database, a cache, a message broker, a search engine. In kubenest, addons can be deployed in two ways: as a component inside an App (tightly coupled to the App’s lifecycle), or as a standalone AddonInstance (independently managed, shareable across multiple Apps). This guide focuses on standalone addon instances.

If you want to bundle an addon with an App, see the Creating and Managing Apps guide and the Addons concept page.


What addon instances are

A standalone AddonInstance is a Helm chart deployment with its own lifecycle: it is created, upgraded, and deleted independently of any App. It lives in a project namespace and exposes exports — key-value outputs like connection strings, passwords, and hostnames — that workload components in the same project can consume via exportRef.

The canonical use case is a shared database: one PostgreSQL instance that two or three Apps in the same project all connect to. Managing it as a standalone instance means you can upgrade the chart, rotate credentials, or adjust resource limits without touching any of the Apps that depend on it.


Available addon types

The AddonDefinition catalog lists the officially supported addon types. Browse it:

list addon definitions
curl -H "Authorization: Bearer $TOKEN" \ "https://api.your-domain.com/api/v1/addon-definitions" | jq '.data[] | {name, chart_name, chart_version}'

Commonly available types:

Definition nameChartDefault export keys
postgresqlbitnami/postgresqlconnection_string, host, port, database, username, password
redisbitnami/redisconnection_string, host, port, password
kafkabitnami/kafkabootstrap_servers, host, port
elasticsearchbitnami/elasticsearchendpoint, host, port, username, password
generic(any chart)(no standard exports; configure manually)

The generic type lets you deploy any Helm chart as an addon instance without a corresponding AddonDefinition. Use it for custom charts or charts not yet in the catalog.


Deploying a standalone addon

Create an addon instance by posting to /api/v1/addon-instances. You must supply the project the instance belongs to and either a definition_id (referencing a catalog entry) or a type + chart directly.

create addon instance from definition
# Get the definition ID first DEFINITION_ID=$(curl -s -H "Authorization: Bearer $TOKEN" \ "https://api.your-domain.com/api/v1/addon-definitions" | \ jq -r '.data[] | select(.name=="postgresql") | .id') curl -X POST https://api.your-domain.com/api/v1/addon-instances \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "my-postgres", "project_id": "b2c3d4e5-0002-0000-0000-000000000000", "definition_id": "'"$DEFINITION_ID"'", "chart_config": { "values": { "auth": { "database": "myapp", "username": "myapp", "password": "mysecretpassword" }, "primary": { "persistence": { "size": "10Gi" } } } } }'

When a definition_id is provided, the backend merges your values on top of the definition’s default values. The chart reference (repo, name, version) comes from the definition — you do not need to specify it.

The response includes the addon instance id and initial phase: pending. The operator deploys the Helm chart asynchronously.


Watching deploy progress

watch addon deploy
INSTANCE_ID="instance-uuid-..." curl -N -H "Authorization: Bearer $TOKEN" \ "https://api.your-domain.com/api/v1/events/stream?addon_instance_id=$INSTANCE_ID"

The phase sequence for a healthy deploy:

pending → deploying → running

deploying can take several minutes for large charts (PostgreSQL with persistence, Kafka with Zookeeper). The operator polls the ArgoCD Application health status and emits a status event each time it changes.


Reading exports

After the addon reaches running, its exports are available on the instance record:

read exports
curl -H "Authorization: Bearer $TOKEN" \ "https://api.your-domain.com/api/v1/addon-instances/$INSTANCE_ID" | jq .exports

Example output for a PostgreSQL instance:

{ "connection_string": "postgresql://myapp:mysecretpassword@my-postgres.my-project.svc.cluster.local:5432/myapp", "host": "my-postgres.my-project.svc.cluster.local", "port": "5432", "database": "myapp", "username": "myapp", "password": "mysecretpassword" }

For addons backed by Kubernetes Secrets (which is the case for all definitions in the catalog), the API response shows export values in plaintext if you have at least project-member access. The values are fetched from the cluster Secret at request time — they are not stored in plaintext in the backend database. If the cluster is disconnected when you request exports, the API returns the last-cached values with a stale: true flag.


Upgrading an addon

Update an addon’s Helm values with a PATCH request. Common reasons to patch: increasing storage size, changing resource requests, enabling a replica set, or rotating a password.

upgrade addon values
curl -X PATCH https://api.your-domain.com/api/v1/addon-instances/$INSTANCE_ID \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "chart_config": { "values": { "primary": { "resources": { "requests": { "memory": "512Mi", "cpu": "250m" }, "limits": { "memory": "1Gi", "cpu": "500m" } } } } }, "note": "Increase memory for production load" }'

The note field is stored on the revision record and appears in the revision history. Use it to leave a human-readable explanation of why the change was made — your future self will thank you.

The PATCH creates a new revision and triggers a helm upgrade. The operator emits status events throughout the upgrade. If the upgrade fails, the revision is marked failed and the previous revision’s values remain active (Helm’s rollback-on-failure behavior).

To upgrade the chart version itself:

upgrade chart version
curl -X PATCH https://api.your-domain.com/api/v1/addon-instances/$INSTANCE_ID \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "chart_config": { "chart": { "version": "16.5.0" } }, "note": "Upgrade postgresql chart to 16.5.0" }'

Revision history and rollback

Every PATCH to an addon instance creates a revision. List the full history:

list revisions
curl -H "Authorization: Bearer $TOKEN" \ "https://api.your-domain.com/api/v1/addon-instances/$INSTANCE_ID/revisions" | \ jq '.[] | {revision_number, created_at, phase, note}'

Example output:

[ { "revision_number": 3, "created_at": "2026-06-11T15:22:00Z", "phase": "success", "note": "Increase memory for production load" }, { "revision_number": 2, "created_at": "2026-06-10T09:41:00Z", "phase": "success", "note": "Enable connection pooling" }, { "revision_number": 1, "created_at": "2026-06-08T14:00:00Z", "phase": "success", "note": "Initial deploy" } ]

Roll back to a prior revision:

rollback by revision number
curl -X POST https://api.your-domain.com/api/v1/addon-instances/$INSTANCE_ID/rollback \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "revision_number": 1, "note": "Reverting memory increase — caused OOMKill on nodes" }'

You can also roll back by revision_id (UUID) if you have it from a previous API call. The rollback creates a new revision (revision 4 in this example) with the values from the target revision — the history remains intact and linear.

Rolling back an addon’s chart version can involve a Helm downgrade. Helm supports this mechanically, but many database charts are not designed for version downgrades — they may run schema migrations on upgrade that cannot be reversed. Always snapshot the database before rolling back a stateful addon to a prior chart version.


Attaching a standalone addon to an App

To wire a standalone addon instance’s exports into a workload component that belongs to an existing App, reference the instance by ID in the component’s exportRef:

patch app to wire standalone addon
INSTANCE_ID="c3d4e5f6-..." curl -X PATCH https://api.your-domain.com/api/v1/apps/my-project/my-app \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "components": [ { "name": "api", "op": "patch", "workload_spec": { "env": [ { "name": "DATABASE_URL", "export_ref": { "addon_instance_id": "'"$INSTANCE_ID"'", "export_key": "connection_string" } } ] } } ] }'

This PATCH triggers a full reconcile of the api component: the operator re-renders its Helm values with the resolved DATABASE_URL and pushes a rolling update. The standalone addon instance is not modified.

You can wire the same addon instance into multiple Apps simultaneously. The addon is unaware of how many workloads depend on it.


Deleting an addon instance

Deleting an addon instance uninstalls the Helm release, removes all Kubernetes resources it created (including Persistent Volume Claims by default), and removes the instance record from the backend.

delete addon instance
curl -X DELETE https://api.your-domain.com/api/v1/addon-instances/$INSTANCE_ID \ -H "Authorization: Bearer $TOKEN"

To preserve the Persistent Volume Claims (and therefore the data), pass preserve_pvcs=true:

delete but keep PVCs
curl -X DELETE \ "https://api.your-domain.com/api/v1/addon-instances/$INSTANCE_ID?preserve_pvcs=true" \ -H "Authorization: Bearer $TOKEN"

Check dependent workloads before deleting. If any App workload component has an exportRef pointing to this addon instance, deleting the instance will cause those environment variables to resolve to empty strings on the next reconcile. The workloads will not immediately crash, but the next pod restart will start without the expected configuration.

Always audit dependencies before deleting a shared addon:

curl -H "Authorization: Bearer $TOKEN" \ "https://api.your-domain.com/api/v1/addon-instances/$INSTANCE_ID/dependents" | jq .

Common pitfalls

Export keys vary for custom (definition-less) addons. The standard export keys (connection_string, host, port, etc.) are a convention defined in the AddonDefinition. For a generic type addon without a definition, kubenest cannot auto-discover exports — they will be empty. You must read the relevant values from the Kubernetes Secret the chart creates and set them manually as workload environment variables, or create a custom AddonDefinition that specifies the export schema.

deploying phase that never transitions to running. The most common cause is the chart’s readiness probe never passing — typically because a password is too long (some chart versions have PostgreSQL password length limits), the PVC cannot be provisioned (storage class unavailable), or the image pull is failing. Check the ArgoCD Application in the cluster for the detailed Helm release status.

Upgrading to a chart version that drops a values key you are using. If a chart upgrade removes a values key your chart_config.values specifies, Helm will typically ignore the extra key — but the behavior is chart-specific. Always read the chart’s changelog before upgrading a minor or major version.


See also:

  • Addons — concept-level explanation of AddonDefinitions, exports, and the two deployment patterns
  • Creating and Managing Apps — how to bundle an addon as an App component using depends_on and exportRef
  • Stack Templates — how to capture an App with addon components as a parameterized reusable template
Last updated on