Skip to content

Middleware

Deploy Middleware on Kubernetes — an open-source DORA metrics platform that measures Deployment Frequency, Lead Time for Changes, MTTR, and Change Failure Rate for engineering teams. Connects to GitHub, Jira, PagerDuty, and CI/CD pipelines to aggregate data automatically.

Persistence is required — losing /app/keys breaks all integrations

Middleware stores generated API keys for all configured integrations (GitHub, Jira, PagerDuty, etc.) in /app/keys. If the PVC is lost or persistence.enabled: false, all integration credentials are destroyed and must be reconfigured manually. Always use persistence.enabled: true in production.

Key Features

  • All four DORA metrics — Deployment Frequency, Lead Time for Changes, MTTR, Change Failure Rate
  • Single all-in-one container — frontend (Next.js), analytics API, and sync server in one image
  • Three internal services — frontend on port 3333, analytics on 9696, sync on 9697
  • PostgreSQL + Redis — bundled subcharts or external connections
  • API key persistence — integration credentials stored in PVC at /app/keys
  • Timezone-aware — configurable timezone for accurate DORA metric windows

Architecture Note

Single instance only — no horizontal scaling

Middleware runs all three services (frontend, analytics, sync) in a single pod. It cannot be horizontally scaled. Plan for at least 4 GB RAM for development and 16 GB RAM for production workloads processing large git histories and pipeline data. The startup probe allows up to 2.5 minutes for the container to initialize all internal services.

Installation

HTTPS repository:

helm repo add helmforge https://repo.helmforge.dev
helm repo update
helm install middleware helmforge/middleware -f values.yaml

OCI registry:

helm install middleware oci://ghcr.io/helmforgedev/helm/middleware -f values.yaml

Deployment Examples

# values.yaml — Middleware with bundled PostgreSQL and Redis subcharts
postgresql:
  enabled: true
  auth:
    database: mhq-oss
    username: middleware
    password: 'set-a-strong-password'

redis:
  enabled: true
  architecture: standalone

middleware:
  timezone: America/Sao_Paulo # affects DORA metric time windows

persistence:
  enabled: true
  size: 1Gi

ingress:
  enabled: true
  ingressClassName: traefik
  hosts:
    - host: middleware.example.com
      paths:
        - path: /
          pathType: Prefix
# values.yaml — Middleware with external PostgreSQL and Redis
postgresql:
  enabled: false

redis:
  enabled: false

externalDatabase:
  enabled: true
  host: postgres.database.svc.cluster.local
  port: 5432
  name: mhq-oss # default DB name — must match what you create on the server
  user: middleware
  existingSecret: middleware-db-credentials
  existingSecretPasswordKey: user-password

externalRedis:
  enabled: true
  host: redis.cache.svc.cluster.local
  port: 6379

middleware:
  timezone: UTC

persistence:
  enabled: true
  size: 1Gi

ingress:
  enabled: true
  ingressClassName: traefik
  hosts:
    - host: middleware.example.com
      paths:
        - path: /
          pathType: Prefix
# values.yaml — Production Middleware with resources and TLS
postgresql:
  enabled: true
  auth:
    database: mhq-oss
    username: middleware
    password: 'strong-db-password'

redis:
  enabled: true
  architecture: standalone

middleware:
  timezone: UTC
  environment: prod
  extraEnv:
    - name: NEXT_PUBLIC_APP_URL
      value: 'https://middleware.example.com'

persistence:
  enabled: true
  size: 1Gi

resources:
  requests:
    memory: 2Gi
    cpu: 500m
  limits:
    memory: 8Gi # 16GB recommended for large orgs with long git histories
    cpu: '4'

ingress:
  enabled: true
  ingressClassName: traefik
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
  hosts:
    - host: middleware.example.com
      paths:
        - path: /
          pathType: Prefix
  tls:
    - secretName: middleware-tls
      hosts:
        - middleware.example.com

Configuration Reference

Core

ParameterTypeDefaultDescription
nameOverridestring""Override the chart name.
fullnameOverridestring""Override the full release name.
commonLabelsobject{}Extra labels added to all resources.

Image

ParameterTypeDefaultDescription
image.repositorystringdocker.io/middlewareeng/middlewareMiddleware container image.
image.tagstring"0.3.1"Image tag.
image.pullPolicystringIfNotPresentImage pull policy.
imagePullSecretsarray[]Pull secrets for private registries.

Middleware Configuration

ParameterTypeDefaultDescription
middleware.frontendPortinteger3333Frontend (Next.js) listen port inside the container.
middleware.analyticsPortinteger9696Analytics API listen port inside the container.
middleware.syncPortinteger9697Sync server listen port inside the container.
middleware.environmentstringprodApplication environment.
middleware.timezonestringUTCTimezone for DORA metric time windows. Use IANA format (e.g. America/Sao_Paulo).
middleware.internalDbEnabledstring"false"Controls the internal DB built into the image. Set to "false" when using subcharts.
middleware.internalRedisEnabledstring"false"Controls the internal Redis built into the image. Set to "false" when using subcharts.
middleware.extraEnvarray[]Extra environment variables for the container.
Set timezone to match your team's working hours

Middleware uses the timezone to calculate DORA metric windows (e.g. business hours for Deployment Frequency). If left at UTC and your team works in America/Sao_Paulo, deployment windows will shift by 3 hours, skewing the metrics.

External Database

Used when postgresql.enabled: false.

ParameterTypeDefaultDescription
externalDatabase.enabledbooleanfalseUse an external PostgreSQL instead of the subchart.
externalDatabase.hoststring""External PostgreSQL hostname.
externalDatabase.portinteger5432External PostgreSQL port.
externalDatabase.namestringmhq-ossDatabase name. Must match what you create on the server.
externalDatabase.userstringmiddlewareDatabase username.
externalDatabase.passwordstring""Database password (prefer existingSecret).
externalDatabase.existingSecretstring""Existing secret with database credentials.
externalDatabase.existingSecretPasswordKeystringuser-passwordKey inside the existing secret for the password.

External Redis

Used when redis.enabled: false.

ParameterTypeDefaultDescription
externalRedis.enabledbooleanfalseUse an external Redis instead of subchart.
externalRedis.hoststring""External Redis hostname.
externalRedis.portinteger6379External Redis port.

Persistence

ParameterTypeDefaultDescription
persistence.enabledbooleantrueEnable PVC for /app/keys (API keys for all integrations).
persistence.sizestring1GiPVC size. Integration keys are small — 1Gi is sufficient.
persistence.storageClassstring""StorageClass for the PVC.
persistence.accessModesarray[ReadWriteOnce]PVC access modes.
persistence.existingClaimstring""Use an existing PVC.

Service

ParameterTypeDefaultDescription
service.typestringClusterIPService type.
service.portinteger80Service port. Routes to the frontend on 3333.
service.annotationsobject{}Annotations for the Service.

Ingress

ParameterTypeDefaultDescription
ingress.enabledbooleanfalseEnable an Ingress resource.
ingress.ingressClassNamestringtraefikIngress class name.
ingress.annotationsobject{}Annotations for the Ingress (e.g. cert-manager).
ingress.hostsarray[]Ingress host and path rules.
ingress.tlsarray[]TLS configuration.

Probes

ParameterTypeDefaultDescription
probes.startup.enabledbooleantrueEnable startup probe.
probes.startup.initialDelaySecondsinteger30Initial delay before first startup check.
probes.startup.periodSecondsinteger5Startup probe period.
probes.startup.failureThresholdinteger30Max failures (30 × 5s = 2.5 min total startup tolerance).
probes.liveness.enabledbooleantrueEnable liveness probe.
probes.liveness.periodSecondsinteger15Liveness probe period.
probes.liveness.failureThresholdinteger3Liveness probe failure threshold.
probes.readiness.enabledbooleantrueEnable readiness probe.
probes.readiness.periodSecondsinteger10Readiness probe period.
probes.readiness.failureThresholdinteger3Readiness probe failure threshold.

Subcharts

ParameterTypeDefaultDescription
postgresql.enabledbooleantrueDeploy bundled PostgreSQL subchart.
postgresql.auth.databasestringmhq-ossDatabase name for Middleware.
postgresql.auth.usernamestringmiddlewareDatabase username.
postgresql.auth.passwordstring""Database password. Auto-generated if empty.
redis.enabledbooleantrueDeploy bundled Redis subchart.
redis.architecturestringstandaloneRedis architecture.

Resources and Security

ParameterTypeDefaultDescription
resourcesobject{}CPU and memory requests and limits.
podSecurityContextobject{}Pod-level security context.
securityContextobject{}Container-level security context.

Scheduling

ParameterTypeDefaultDescription
nodeSelectorobject{}Node selector for scheduling.
tolerationsarray[]Tolerations for scheduling.
affinityobject{}Affinity rules.
topologySpreadConstraintsarray[]Topology spread constraints.
priorityClassNamestring""PriorityClass for the pod.
terminationGracePeriodSecondsinteger30Termination grace period.
podLabelsobject{}Extra labels for the pod.
podAnnotationsobject{}Extra annotations for the pod.

Extra

ParameterTypeDefaultDescription
extraVolumesarray[]Extra volumes to attach to the pod.
extraVolumeMountsarray[]Extra volume mounts for the container.
extraManifestsarray[]Extra Kubernetes manifests deployed alongside the chart.

More Information