Platform Backend

Platform Deployment

Both services run on Kubernetes and are deployed by the GitLab pipeline (.gitlab-ci.yml) with the Helm charts in deploy/ (Helm Charts). There is one cluster per production region — EU and US — and a development cluster for the issue and develop environments. What a running deployment reports about itself is described in Observability.

Container Images

Image How it is built

backend

backend/Dockerfile: a Temurin 21 base image (Ubuntu 22.04) with ffmpeg from the Ubuntu packages, which re-encodes uploaded videos (Re-encoding of Uploaded Videos), the distribution archive from ./gradlew :promethist-platform-backend:distTar unpacked into /app, plus backend/lib (the OpenTelemetry Java agent) copied into /app/lib. It runs app/bin/promethist-platform-backend as an unprivileged user and exposes 9310.

frontend-eu, frontend-com, frontend-issue, frontend-develop

frontend/Dockerfile: node:20-alpine with the output of npm run build, the production dependencies and the .env* files the build job wrote. Because the Studio’s NEXT_PUBLIC_* variables and its secrets are fixed at build time, there is one frontend image per target: frontend-eu and frontend-com (the US region) for preview and production, frontend-issue and frontend-develop for the development cluster.

Images are pushed to the project’s GitLab registry as $CI_REGISTRY_IMAGE/{name}. Merge-request builds are tagged with the short commit SHA; release builds with the Git tag and latest.

Pipeline

Pipelines run only for Git tags and for merge requests whose source branch is release/* or PRP-*. A push to main or to any other branch starts no pipeline.

Trigger What runs

Merge request from PRP-*

KtLint on the changed Kotlin files (gradle:checkFormatting, allowed to fail), the backend distribution, backend and frontend images, and a deployment of both into a per-issue namespace on the development cluster. stop_environment (manual) deletes the namespace again.

Merge request from release/*

The same checks and builds, then deployments to the develop environment and to the preview environments of both regions. Each region’s frontend is built after its backend is deployed.

Tag

Release images, the Helm charts packaged with the tag as their version and published to the shared Helm repository, the production deployments, the GitLab release with notes generated from the changelog API, and the trigger of the public documentation site (Documentation Sites).

The stages are validate, build backend, deploy backend, build frontend, deploy frontend, release and document. The pipeline does not run the backend test suite and does not lint or type-check the Studio beyond what next build does; run those checks locally (Tests, Code Conventions).

Environments

Environment Trigger Host Notes

Issue

MR from PRP-{id}-*

platform-{id}.promethist.dev

Namespace promethist-platform-{id} on the development cluster, prepared by deploy/prepare-namespace.sh. One replica, 1 GiB backend memory (65 % of it heap), spot nodes, no re-encoding of uploaded videos. There is no engine in the namespace: an ExternalName service named promethist-engine points at the development engine. The Studio signs in against the development Keycloak.

Develop

MR from release/*

platform.promethist.dev

Shared development environment in the default namespace of the development cluster.

Preview

MR from release/*

preview.eu.promethist.ai, preview.us.promethist.ai

The release candidate, in the preview namespace of each production cluster. Preview shares the production Elasticsearch cluster, which is why its conversation-data index patterns carry the preview namespace segment.

Production

Tag

eu.promethist.ai, us.promethist.ai

The default namespace of each production cluster. EU deploys automatically; the US backend deployment is a manual job, and the US frontend build waits for it.

Configuration and Secrets

Where What

Backend ConfigMap → /config/application.properties

app.domain, app.namespace, app.version, the MongoDB database name (the release name), the six promethist.mcp.* URLs of the environment’s host, the conversation-data index patterns, the bridge and engine URLs of the test suites, and whether uploaded videos are re-encoded.

Azure Key Vault → /config/application-default.properties

Everything secret or environment-specific beyond that: database and Elasticsearch connections, provider keys, Stripe, Mailgun, storage. The Key Vault object promethist-platform-backend is projected by the Secrets Store CSI driver through the azure-secret-provider SecretProviderClass (deploy/secret-provider.yaml), which also provides the registry pull secret.

{release}-testing Secret → environment variables

The bridge token and the engine test identity, from the BRIDGE_SECRET_TOKEN_* and ENGINE_BASIC_IDENTITY_* CI variables. Both are optional; without them test suites and sign-in-gated live tests are unavailable.

Frontend .env.production (inside the image)

Written by the npm:build * job: the Keycloak client and issuer, the NextAuth secret, the public URLs of the target environment and the MCP OAuth settings, including the region’s signing key from the MCP_OAUTH_PRIVATE_JWK_EU, _US or _PREVIEW CI variable.

The precedence of these sources is described in Configuration.

Release Flow

  1. Work is done on PRP-{id}-… branches. Their merge requests get an issue environment and are merged into the current release branch.

  2. The release branch release/{n} has a merge request towards main. Every push to it redeploys develop and both preview environments, which is where a release is tested.

  3. A release is squash-merged into main as a single commit named Release/{n}. Pushing main starts no pipeline.

  4. A Git tag on that commit — {year}.{week}.{patch}, for example 2026.39.0 — starts the production pipeline. Hotfixes are merged into main directly and released with a new patch tag.

  5. After the release the release branch is recreated from main for the next round of work.

A tag pipeline can end as failed only because its last job — the trigger of the public documentation site — failed. Check the deployment jobs, not the pipeline status, to see what reached production. The /api/version endpoint of a host reports the engine’s version, not the platform’s.

In this section