Skip to main content

Configuration Reference

Complete reference for Helm values configuration.

Global Settings

global:
# Environment: development, staging, production
environment: production

# Image registry prefix (for private registries)
imageRegistry: "your-registry.example.com"

# Image pull secrets for private registries
imagePullSecrets:
- name: regcred

# RDS SSL configuration (for AWS RDS)
rdsSSL:
enabled: true

Proxy & Network

See the dedicated Network & Proxy Configuration page for full details.

global:
proxy:
httpsProxy: "http://proxy.corp.example.com:3128"
httpProxy: ""
noProxy: "*.internal.corp.com"

networkPolicies:
enabled: false
allowedExternalCIDRs: []
allowDNS: true

Connector API Base URL Overrides

connectors:
slack:
apiBaseUrl: "" # Override Slack API base URL
teams:
graphApiBaseUrl: "" # Override Microsoft Graph API base URL
jira:
apiBaseUrl: "" # Override Jira/Atlassian API base URL
github:
apiBaseUrl: "" # Override GitHub API base URL (or GitHub Enterprise)
linear:
apiBaseUrl: "" # Override Linear API base URL

Database

database:
# Name of the Kubernetes secret containing database credentials
secretName: align-database

# Secret should contain:
# url: postgresql://user:pass@host:port/dbname
# host: hostname (for health checks)
# port: 5432
# username: database user
# password: database password

Connection Pooling

Align's historical scan feature (Discover) processes items in parallel, which can put pressure on database connections. We provide several options depending on your infrastructure.

The Helm chart includes an optional PgBouncer sidecar that provides enterprise-grade connection pooling on any cloud provider (AWS, GCP, Azure, on-premises):

  • Cost: Free (runs as a sidecar container)
  • Benefits: Connection multiplexing (1000 app connections → 50 DB connections), works everywhere
  • Configuration: Enable in your values override
gateway:
pgbouncer:
enabled: true
# Pool mode: transaction (recommended), session, or statement
poolMode: "transaction"
# Maximum connections from the gateway to PgBouncer
maxClientConnections: 1000
# Connections PgBouncer maintains to PostgreSQL
defaultPoolSize: 50
minPoolSize: 10
reservePoolSize: 5
extraEnv:
# With PgBouncer, you can use higher concurrency
- name: SQS_IMPORT_WORKER_CONCURRENCY
value: "30"

When enabled, the gateway automatically routes database connections through the PgBouncer sidecar running on localhost:6432.

Option 2: RDS Proxy (AWS)

If you're running on AWS, RDS Proxy is a managed alternative:

  • Cost: ~$22/month
  • Benefits: Connection multiplexing, automatic failover, IAM authentication
  • Configuration: Point DATABASE_URL to the proxy endpoint instead of RDS directly

Setup steps:

  1. Create RDS Proxy in AWS (via Console, CLI, or Terraform):

    • Target your PostgreSQL RDS instance
    • Create an IAM role with Secrets Manager access
    • Configure security group to allow traffic from your EKS cluster
  2. Update your database secret to use the proxy endpoint:

    kubectl create secret generic align-database \
    --namespace align \
    --from-literal=url="postgresql://user:pass@my-proxy.proxy-xxx.us-east-1.rds.amazonaws.com:5432/align?sslmode=require" \
    --from-literal=host="my-proxy.proxy-xxx.us-east-1.rds.amazonaws.com" \
    --from-literal=port="5432" \
    --from-literal=username="user" \
    --from-literal=password="pass" \
    --from-literal=database="align"
  3. Helm values - PgBouncer is disabled by default, so no changes needed:

    gateway:
    pgbouncer:
    enabled: false # Default, no sidecar needed with RDS Proxy
    extraEnv:
    # With RDS Proxy, you can use higher concurrency
    - name: SQS_IMPORT_WORKER_CONCURRENCY
    value: "30"
    # App pool is just for local buffering
    - name: PG_POOL_MAX
    value: "10"

RDS Proxy is transparent to the application - you simply point DATABASE_URL to the proxy endpoint instead of the direct RDS endpoint.

Option 3: Application-Level Pooling (Fallback)

Without connection pooling, Align includes automatic retry with exponential backoff for connection pool exhaustion:

gateway:
pgbouncer:
enabled: false
extraEnv:
# Keep workers <= pool_size * num_replicas / 2
# Example: 2 replicas, pool=15 → workers=15 max
- name: SQS_IMPORT_WORKER_CONCURRENCY
value: "15"
# Size based on your PostgreSQL max_connections
- name: PG_POOL_MAX
value: "15"

Tuning guidelines (without pooling):

  • Check your PostgreSQL max_connections (typically 100-200)
  • Reserve ~20 connections for admin/migrations
  • Divide remaining by number of services (gateway + brain)
  • Set PG_POOL_MAX to that value per service
  • Set SQS_IMPORT_WORKER_CONCURRENCY to PG_POOL_MAX * num_replicas / 2

Tenant Isolation: the restricted align_app role

Align enforces tenant isolation at two layers: the application always scopes queries to a single tenant (withTenant), and PostgreSQL Row-Level Security (RLS) is a hard backstop that filters every row by tenant_id. RLS only protects you if the app connects as a non-owner role - PostgreSQL lets a table owner bypass RLS. Connecting as the database owner (e.g. the RDS master user) removes that backstop.

The migrations create a restricted role named align_app (NOLOGIN by default) and grant it exactly the privileges the app needs (SELECT/INSERT/UPDATE/DELETE on tenant tables plus EXECUTE on the pre-auth lookup functions). To turn the backstop on, give it a login and point the app at it:

  1. Give align_app a password and the LOGIN attribute (run as a superuser/owner, once):

    ALTER ROLE align_app WITH LOGIN PASSWORD 'a-strong-password';
  2. Point the application at the restricted role. The gateway prefers DATABASE_APP_URL over DATABASE_URL, so you can leave migrations running as the owner while the running app uses align_app:

    gateway:
    extraEnv:
    - name: DATABASE_APP_URL
    valueFrom:
    secretKeyRef:
    name: align-database
    key: app-url # postgres://align_app:...@host:5432/align

    For Brain, set POSTGRES_USER/POSTGRES_PASSWORD to the align_app credentials.

  3. Keep migrations running as the owner. The migration job must stay on the owner connection (DATABASE_URL) because it creates roles, tables and FORCE RLS policies. Only the long-running gateway and brain processes switch to align_app.

  4. Verify RLS is actually enforced (should return only the current tenant's rows):

    SET ROLE align_app;
    SELECT set_config('app.current_tenant', '<tenant-uuid>', false);
    SELECT count(*) FROM decision_snapshots; -- only this tenant's rows
    RESET ROLE;

If you skip this, Align still isolates tenants at the application layer, but you lose the database-level backstop - a single missed withTenant would no longer be caught by RLS.

Data Retention

Align is built to store decisions, not your raw messages. Verbatim message, PR, and commit text is not retained at rest:

  • Live capture (real-time / @mention / webhook) is process-then-discard: the original text is used transiently for analysis, then nulled before the decision is stored. Only the distilled decision plus a source_url (a link back to the original in your own tool) is kept.
  • Discover / historical import never stores raw content either. The import_suggestions.raw_content column is always written empty, and a database CHECK constraint (import_suggestions_raw_content_empty) enforces this - the schema itself proves raw content is not retained, so it is safe to audit.
  • Import jobs are purged on a schedule. cleanup_old_import_jobs() deletes import jobs, batches, and suggestions for completed/failed jobs older than 33 days (run by the gateway's data-cleanup scheduler). Approved decisions are kept; the transient import scaffolding is not.

The retained decision content lives in decision_snapshots. In the managed deployment this sits on RDS with at-rest encryption (KMS-backed); in a self-host deployment, ensure your PostgreSQL storage is encrypted at rest according to your own infrastructure standards.

Gateway (API Server)

gateway:
enabled: true
replicaCount: 2

# Frontend URL for decision links in Slack/Teams
frontendUrl: "https://app.yourdomain.com"

image:
repository: align/gateway
tag: latest
pullPolicy: IfNotPresent

resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"

service:
type: ClusterIP
port: 8080

# Autoscaling
autoscaling:
enabled: true
minReplicas: 2
maxReplicas: 10
targetCPUUtilizationPercentage: 70

# Pod Disruption Budget
pdb:
enabled: true
minAvailable: 1

# Ingress
ingress:
enabled: true
className: "nginx" # or "traefik"
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
hosts:
- host: api.yourdomain.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: api-tls
hosts:
- api.yourdomain.com

# Redis for job state and real-time progress (required for multi-pod deployments)
# For single-pod deployments, leave empty to use in-memory storage
# Works with any Redis-compatible service: ElastiCache, Memorystore, Azure Cache, Dragonfly, KeyDB
redis:
# Direct URL (e.g., redis://host:6379 or rediss://user:pass@host:6379)
url: ""
# Or use a Kubernetes secret:
secretName: ""
secretKey: "url"

# Message queues for distributed job processing (optional)
# Leave empty for in-memory queue (works for single-pod and most deployments)
# For multi-pod high-volume deployments, configure SQS (AWS) queue URLs
# The queue backend is pluggable - see QueueBackend<T> interface for adding new providers
sqs:
# Queue for Discover historical scans
importJobQueueUrl: ""
# Queue for bulk approval with cross-linkage
bulkApprovalQueueUrl: ""
# Queue for bulk delete operations
bulkDeleteQueueUrl: ""

# PgBouncer sidecar for connection pooling (recommended for self-hosted)
# See "Connection Pooling" section above for details
pgbouncer:
enabled: false
image:
repository: bitnami/pgbouncer
tag: "1.23.1"
poolMode: "transaction"
maxClientConnections: 1000
defaultPoolSize: 50
minPoolSize: 10
reservePoolSize: 5
resources:
requests:
memory: "64Mi"
cpu: "50m"
limits:
memory: "128Mi"
cpu: "200m"

# OIDC Authentication (for self-hosted SSO)
# Allows you to use your own identity provider (Azure AD, Okta, Auth0, Keycloak)
oidc:
enabled: true
scopes: "openid email profile"
# For single-tenant deployments, set this to your tenant ID:
defaultTenantId: "your-tenant-uuid"

# Additional environment variables
extraEnv:
- name: LOG_LEVEL
value: "info"

Schema Version Guard

The gateway refuses to start (and /ready returns 503) if the database schema is behind the migrations this gateway build requires. This turns the "app ahead of database" drift into a loud, immediate failure instead of silent write corruption. See Upgrades → Schema Version Guard for the runbook.

VariableDefaultDescription
SCHEMA_CHECK_MODEenforceenforce = refuse to start / 503 when the DB is behind; warn = log and start anyway; off = disable the check. Keep enforce in production.
gateway:
extraEnv:
- name: SCHEMA_CHECK_MODE
value: "enforce"
Keep the migrations and gateway image tags in lockstep

The guard catches the case where the migrations image tag lags the gateway image tag. To avoid tripping it on every upgrade, set both image tags to the same release in your Helm values.

Discover (Historical Scan) Tuning

The Discover feature scans your connected platforms for historical decisions. It uses platform-specific batch sizes and confidence thresholds optimized for each connector:

PlatformBatch SizeMin ConfidenceNotes
Slack120.20Larger batches - thread items are shorter
Teams120.20Similar to Slack - chat-based items
GitHub80.30Medium batches - PRs/issues with comments
Jira80.30Medium batches - structured ticket content
Confluence80.30Medium batches - document-style content

These defaults are tuned for optimal detection quality and speed. You can override them with environment variables:

gateway:
extraEnv:
# Override minimum confidence threshold for all platforms (default: platform-specific)
# Items below this threshold are filtered out. Lower values catch more
# borderline decisions for human review. Range: 0.0-1.0
- name: IMPORT_MIN_CONFIDENCE
value: "0.2"

# Worker concurrency - number of parallel batch processors (default: 12 in-memory, 20 SQS)
# Higher = faster scans but more database connections consumed.
# Must be < PG_POOL_MAX to leave headroom for API requests.
- name: SQS_IMPORT_WORKER_CONCURRENCY
value: "20"

# Application connection pool size per gateway replica (default: 15)
# Total DB connections = PG_POOL_MAX × number of gateway replicas
# Ensure this fits within your PostgreSQL max_connections
- name: PG_POOL_MAX
value: "25"

# Database statement timeout in milliseconds (default: 120000 = 2 min)
# Increase for large tenant scans that process thousands of items
- name: PG_STATEMENT_TIMEOUT
value: "300000"

# --- Parallelism Settings ---
# These control concurrent API calls to connectors during scanning.
# Higher values = faster scans but more API rate limit pressure.

# Parallel Slack channels to scan simultaneously (default: 10)
- name: IMPORT_PARALLEL_CHANNELS
value: "10"

# Parallel thread fetches for Slack/Teams (default: 20)
- name: IMPORT_PARALLEL_THREADS
value: "20"

# Parallel comment fetches for Jira/GitHub (default: 20)
- name: IMPORT_PARALLEL_COMMENTS
value: "20"

# Parallel meeting fetches for Teams (default: 10)
- name: IMPORT_PARALLEL_MEETINGS
value: "10"

# Maximum parallel GitHub repos to scan simultaneously (default: 10)
# Higher values speed up GitHub scans but increase API rate limit pressure
- name: IMPORT_PARALLEL_REPOS
value: "10"

# Parallel GitHub detail fetches per repo (default: 20)
# Controls concurrent issue/PR detail API calls within each repo
- name: IMPORT_PARALLEL_GITHUB_DETAILS
value: "20"

Performance tips:

  • Single-pod deployments: Use SQS_IMPORT_WORKER_CONCURRENCY=12 (default) and PG_POOL_MAX=15
  • Multi-pod with Redis: Use SQS_IMPORT_WORKER_CONCURRENCY=20-30 and PG_POOL_MAX=25-40
  • With PgBouncer: You can safely increase SQS_IMPORT_WORKER_CONCURRENCY=30+ since PgBouncer handles connection multiplexing
  • Large organizations (1000+ items): Increase SQS_IMPORT_WORKER_CONCURRENCY and add Brain replicas for more parallel LLM analysis
  • Slack and Teams benefit most from lower confidence thresholds, as thread-based discussions often contain implicit decisions
  • The Brain service dynamically scales its LLM token budget based on batch size, so no tuning is needed on the Brain side
IMPORT_BATCH_SIZE is now a global override

Batch sizes are now platform-specific and optimized automatically (Slack/Teams: 12, GitHub/Jira: 8). If IMPORT_BATCH_SIZE is set, it acts as a global override for all platforms. In most cases you can safely remove this variable; if you keep it, it will override all platform-specific defaults.

OIDC Authentication

Self-hosted deployments can use their own identity provider for single sign-on (SSO). Align supports any OIDC-compliant provider:

  • Azure AD / Entra ID
  • Okta
  • Auth0
  • Keycloak
  • Google Workspace

Setup Steps

  1. Create an OAuth application in your identity provider:

    • Set the redirect URI to https://api.yourdomain.com/auth/callback
    • Enable the openid, email, and profile scopes
    • Note your Client ID and Client Secret
  2. Create the OIDC secret:

    kubectl create secret generic align-oidc \
    --namespace align \
    --from-literal=issuer-url="https://login.microsoftonline.com/{tenant-id}/v2.0" \
    --from-literal=client-id="your-client-id" \
    --from-literal=client-secret="your-client-secret"
  3. Enable OIDC in your values:

    gateway:
    oidc:
    enabled: true
    scopes: "openid email profile"
    defaultTenantId: "your-align-tenant-uuid" # For single-tenant deployments
  4. Deploy with helm upgrade

Provider-Specific Configuration

Azure AD / Entra ID

Issuer URL: https://login.microsoftonline.com/{tenant-id}/v2.0

  1. Go to Azure Portal → Azure Active Directory → App registrations
  2. Create a new registration
  3. Add a redirect URI: https://api.yourdomain.com/auth/callback
  4. Generate a client secret
  5. Grant openid, email, and profile permissions
Okta

Issuer URL: https://{your-domain}.okta.com

  1. Create a new OIDC Web Application in Okta Admin
  2. Set the redirect URI: https://api.yourdomain.com/auth/callback
  3. Note the Client ID and Client Secret
Keycloak

Issuer URL: https://{host}/realms/{realm}

  1. Create a new client in your realm
  2. Set Access Type to "confidential"
  3. Add the redirect URI: https://api.yourdomain.com/auth/callback
  4. Enable "Standard Flow"

Map directory groups to roles

By default every SSO/SCIM-provisioned user is created as a member. To grant org_admin or viewer from your identity provider's directory groups, configure a group -> role mapping. This works across OIDC login, SAML login, and SCIM provisioning.

Valid roles: org_admin, member, viewer.

VariableApplies toPurpose
SSO_GROUP_ROLE_MAPPINGOIDC + SAMLJSON object mapping a directory group name to an Align role
SSO_GROUPS_CLAIMOIDCToken claim that lists the user's groups (default groups)
SAML_GROUPS_ATTRIBUTESAMLAssertion attribute that lists the user's groups (default groups)
# Example: members of "Eng-Admins" become org_admin, "ReadOnly" become viewer.
SSO_GROUP_ROLE_MAPPING='{"Eng-Admins":"org_admin","ReadOnly":"viewer"}'
SSO_GROUPS_CLAIM=groups # OIDC: ensure your IdP emits a groups claim in the ID token
SAML_GROUPS_ATTRIBUTE=groups # SAML: the attribute name in the assertion

For SCIM, set the role per group via the SCIM Group API using the alignRole attribute on create (POST /scim/v2/Groups) or patch (op: replace, path: alignRole). A user's effective role is the most privileged role across all the groups they belong to.

Behavior notes:

  • Most privileged wins. A user in both an admin group and a viewer group becomes org_admin.
  • Re-synced on every login. Removing a user from the admin group in your IdP demotes them on their next login (directory-driven access control).
  • Manual overrides are sticky. If an org admin changes a user's role in the Align UI, that role is marked manual and directory sync will not overwrite it.
  • Fail-open. Invalid mapping JSON is ignored (logged as a warning), and a login where no group matches keeps the user's existing role - directory sync never locks anyone out. The last active org_admin of a tenant is never demoted by login sync.

Brain (AI Service)

brain:
enabled: true
replicaCount: 2

image:
repository: align/brain
tag: latest

resources:
requests:
memory: "512Mi"
cpu: "200m"
limits:
memory: "1Gi"
cpu: "1000m"

service:
type: ClusterIP
port: 8090

# Probe configuration (brain handles long-running LLM calls)
livenessProbe:
initialDelaySeconds: 30
periodSeconds: 60
timeoutSeconds: 30
failureThreshold: 5

readinessProbe:
initialDelaySeconds: 10
periodSeconds: 30
timeoutSeconds: 15
failureThreshold: 6

autoscaling:
enabled: true
minReplicas: 2
maxReplicas: 8
targetCPUUtilizationPercentage: 70

extraEnv: []

GPU Inference (Optional)

Enable local LLM inference on GPU nodes. In the default scan-only mode, this offloads high-throughput operations to the local GPU while keeping cloud APIs for quality-critical synthesis. Set LOCAL_LLM_FOR_SCANS_ONLY=false to route all operations locally and eliminate cloud API costs entirely.

gpu:
# NVIDIA device plugin DaemonSet
# Detects GPU resources on nodes and exposes them to Kubernetes
devicePlugin:
enabled: false
image:
repository: nvcr.io/nvidia/k8s-device-plugin
tag: "v0.17.0"

# vLLM inference server (OpenAI-compatible API)
llmServer:
enabled: false
replicaCount: 1
image:
# Use vllm/vllm-openai for open-source models
# Use registry.align.tech/align/llm-server for Align's fine-tuned models (Enterprise)
repository: vllm/vllm-openai
tag: "v0.8.5"
port: 8001
resources:
requests:
memory: "14Gi"
cpu: "2000m"
nvidia.com/gpu: "1"
limits:
memory: "16Gi"
cpu: "4000m"
nvidia.com/gpu: "1"
# Pass additional args/env to vLLM (e.g., model name, quantization)
extraEnv:
- name: MODEL_NAME
value: "meta-llama/Llama-3.1-8B-Instruct"

Requirements:

  • GPU nodes with NVIDIA drivers (e.g., AWS al2023-nvidia AMI, or install nvidia-driver + nvidia-container-toolkit)
  • Node label: node-type: gpu
  • Node taint: nvidia.com/gpu=true:NoSchedule

When gpu.llmServer.enabled is true, the Helm chart automatically injects LOCAL_LLM_SERVER_URL into Brain pods. By default, LOCAL_LLM_FOR_SCANS_ONLY=true routes high-throughput operations (Discover scans, bulk analysis) to the local GPU while keeping synthesis on cloud APIs for quality. Set LOCAL_LLM_FOR_SCANS_ONLY=false in Brain's extraEnv to route all operations to the local GPU.

See LLM Configuration for full GPU setup guide.

UI (Frontend)

ui:
enabled: true
replicaCount: 2

image:
repository: align/ui
tag: latest

resources:
requests:
memory: "128Mi"
cpu: "50m"
limits:
memory: "256Mi"
cpu: "200m"

service:
type: ClusterIP
port: 3000

ingress:
enabled: true
className: "nginx"
hosts:
- host: app.yourdomain.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: app-tls
hosts:
- app.yourdomain.com

extraEnv: []

Connectors

connectors:
# Common settings for all connectors
common:
resources:
requests:
memory: "128Mi"
cpu: "50m"
limits:
memory: "256Mi"
cpu: "200m"

slack:
enabled: true
replicaCount: 1
image:
repository: align/connector-slack
tag: latest
service:
port: 8081
extraEnv: []

teams:
enabled: true
replicaCount: 1
image:
repository: align/connector-teams
tag: latest
service:
port: 8084
extraEnv: []

jira:
enabled: true
replicaCount: 1
alignCommand: "/align" # Command to trigger capture
image:
repository: align/connector-jira
tag: latest
service:
port: 8083
extraEnv: []

github:
enabled: true
replicaCount: 1
image:
repository: align/connector-github
tag: latest
service:
port: 8085
extraEnv: []

linear:
enabled: false
replicaCount: 1
image:
repository: align/connector-linear
tag: latest
service:
port: 8082
extraEnv: []

# MCP Server for AI Assistants (Claude Desktop, Cursor, VS Code)
align:
enabled: false
replicaCount: 1
image:
repository: align/connector-align
tag: latest
service:
port: 8089
# Expose MCP server externally for remote AI assistants
ingress:
enabled: false
className: "nginx" # or "traefik"
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
hosts:
- host: mcp.yourdomain.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: mcp-tls
hosts:
- mcp.yourdomain.com
extraEnv: []
tip

When the MCP connector is enabled with ingress, AI assistants like Cursor can connect directly to https://mcp.yourdomain.com/tools. For Claude Desktop, you can also use stdio mode (local process) - see AI Assistants Integration.

Secrets

secrets:
# Create secrets from values (DEV ONLY)
create: false

# LLM API keys
llm:
openaiApiKey: ""
anthropicApiKey: ""
custom:
baseUrl: "" # OpenAI-compatible endpoint
model: "" # Model name
apiKey: "" # Optional API key
useLocalEmbeddings: true

# Internal secrets
internal:
encryptionKey: ""
jwtSecret: ""
cookieSecret: ""
serviceAuthToken: ""
note

OAuth credentials are not required. Self-hosted Align uses Align's centrally-managed OAuth apps for connector authentication.

External Secrets

Align supports the External Secrets Operator for syncing secrets from your cloud provider's secret manager.

AWS Secrets Manager

externalSecrets:
enabled: true
secretStore:
name: aws-secrets-manager
kind: ClusterSecretStore
refreshInterval: 1h
aws:
secretPath: "align/production"

GCP Secret Manager

externalSecrets:
enabled: true
secretStore:
name: gcp-secret-manager
kind: ClusterSecretStore
refreshInterval: 1h
gcp:
projectID: "your-project-id"

Azure Key Vault

externalSecrets:
enabled: true
secretStore:
name: azure-key-vault
kind: ClusterSecretStore
refreshInterval: 1h
azure:
vaultUrl: "https://your-vault.vault.azure.net"

HashiCorp Vault

externalSecrets:
enabled: true
secretStore:
name: hashicorp-vault
kind: ClusterSecretStore
refreshInterval: 1h
vault:
server: "https://vault.example.com"
path: "secret/data/align"

Telemetry

telemetry:
enabled: true
samplingRate: "1.0"
batchSize: 100
flushIntervalMs: 5000

# Hourly aggregation CronJob
aggregation:
enabled: true
schedule: "5 * * * *"

# Daily rollup CronJob
dailyRollup:
enabled: true
schedule: "30 1 * * *"

# Data retention (days)
retention:
rawEventDays: 90
hourlyMetricDays: 365
dailyMetricDays: 730

Migrations

migrations:
enabled: true
image:
repository: align/migrations
tag: latest
pullPolicy: Always
resources:
requests:
memory: "64Mi"
cpu: "50m"
limits:
memory: "256Mi"
cpu: "500m"

Security Context

securityContext:
# Enable restrictive security context
# Disable for local dev where containers run as root
enabled: true

Node Scheduling

nodeSelector: {}

tolerations: []

affinity: {}

Service Account

serviceAccount:
create: true
name: align
annotations: {}

Cloud-specific IAM

AWS (IRSA)
serviceAccount:
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::ACCOUNT:role/align-role
GCP (Workload Identity)
serviceAccount:
annotations:
iam.gke.io/gcp-service-account: align@PROJECT.iam.gserviceaccount.com
Azure (Workload Identity)
serviceAccount:
annotations:
azure.workload.identity/client-id: "CLIENT_ID"
labels:
azure.workload.identity/use: "true"