Platform, Configuration & Security¶
Two changes here will stop a 2.0 server from starting or behaving as expected with a 1.13 configuration: the LLM/embedding config move, and the new session limits.
LLM and embedding configuration moved¶
Breaking · Affects: every deployment using semantic search, NLQ, or any LLM feature
Provider configuration is no longer nested inside elasticsearch.naturalLanguageSearch. It moves to a new top-level llmConfiguration block, with embeddings as a sub-section that reuses the same provider credentials.
Removed from elasticSearchConfiguration.naturalLanguageSearch¶
embeddingProvider
maxConcurrentRequests
bedrock.* (awsConfig, modelId, embeddingModelId, embeddingDimension, maxTokens, temperature, timeoutSeconds)
openai.* (apiKey, endpoint, deploymentName, apiVersion, modelId, embeddingModelId, embeddingDimension, maxTokens, temperature, timeoutSeconds)
google.* (apiKey, endpoint, modelId, embeddingModelId, embeddingDimension)
djl.* (embeddingModel)
What remains under naturalLanguageSearch: semanticSearchEnabled, knnNumCandidatesMultiplier (new, default 2) and a new filterExtractor block (cacheMaxSize 1000, cacheExpiryMinutes 5, maxSampleValues).
The 2.0 shape¶
elasticsearch:
naturalLanguageSearch:
semanticSearchEnabled: ${SEMANTIC_SEARCH_ENABLED:-false}
# Embedding provider/model/credentials now live under llmConfiguration.embeddings
llmConfiguration:
enabled: ${LLM_ENABLED:-false}
provider: ${LLM_PROVIDER:-noop} # noop | openai | azureOpenAI | bedrock | google | anthropic
maxConcurrentRequests: ${LLM_MAX_CONCURRENT_REQUESTS:-5}
openai:
apiKey: ${LLM_OPENAI_API_KEY:-""}
modelId: ${LLM_OPENAI_MODEL_ID:-"gpt-4o-mini"}
endpoint: ${LLM_OPENAI_ENDPOINT:-""} # with deploymentName for Azure OpenAI
deploymentName: ${LLM_OPENAI_DEPLOYMENT:-""}
apiVersion: ${LLM_OPENAI_API_VERSION:-"2024-02-01"}
maxTokens: ${LLM_OPENAI_MAX_TOKENS:-4096}
bedrock:
awsConfig:
enabled: ${BEDROCK_AWS_IAM_AUTH_ENABLED:-true}
region: ${AWS_DEFAULT_REGION:-""}
accessKeyId: ${AWS_ACCESS_KEY_ID:-""}
secretAccessKey: ${AWS_SECRET_ACCESS_KEY:-""}
sessionToken: ${AWS_SESSION_TOKEN:-""}
modelId: ${LLM_BEDROCK_MODEL_ID:-"eu.anthropic.claude-haiku-4-5-20251001-v1:0"}
maxTokens: ${LLM_BEDROCK_MAX_TOKENS:-4096}
google:
apiKey: ${LLM_GOOGLE_API_KEY:-""}
modelId: ${LLM_GOOGLE_MODEL_ID:-"gemini-2.5-flash"}
anthropic:
apiKey: ${LLM_ANTHROPIC_API_KEY:-""}
modelId: ${LLM_ANTHROPIC_MODEL_ID:-"claude-3-5-sonnet-20240620"}
baseUrl: ${LLM_ANTHROPIC_BASE_URL:-"https://api.anthropic.com"}
embeddings:
provider: ${EMBEDDING_PROVIDER:-bedrock} # bedrock | openai | google | djl
maxConcurrentRequests: ${MAX_CONCURRENT_EMBEDDING_REQUESTS:-10}
bedrock:
embeddingModelId: ${AWS_BEDROCK_EMBED_MODEL_ID:-"amazon.titan-embed-text-v2:0"}
embeddingDimension: ${AWS_BEDROCK_EMBEDDING_DIMENSION:-512}
openai:
embeddingModelId: ${OPENAI_EMBEDDING_MODEL_ID:-"text-embedding-3-small"}
embeddingDimension: ${OPENAI_EMBEDDING_DIMENSION:-1536}
google:
embeddingModelId: ${GOOGLE_EMBEDDING_MODEL_ID:-"gemini-embedding-001"}
embeddingDimension: ${GOOGLE_EMBEDDING_DIMENSION:-768}
djl:
embeddingModel: ${DJL_EMBEDDING_MODEL:-"ai.djl.huggingface.pytorch/sentence-transformers/all-MiniLM-L6-v2"}
The embedding provider may differ from the chat provider; embeddings reuse the credentials from the provider blocks above (bedrock.awsConfig, openai.apiKey/endpoint, google.apiKey).
Environment variable renames¶
| 1.13 | 2.0 |
|---|---|
AWS_BEDROCK_REGION | AWS_DEFAULT_REGION |
AWS_BEDROCK_ACCESS_KEY | AWS_ACCESS_KEY_ID |
AWS_BEDROCK_SECRET_KEY | AWS_SECRET_ACCESS_KEY |
AWS_BEDROCK_SESSION_TOKEN | AWS_SESSION_TOKEN |
AWS_BEDROCK_MODEL_ID | LLM_BEDROCK_MODEL_ID |
OPENAI_API_KEY | LLM_OPENAI_API_KEY |
OPENAI_API_ENDPOINT | LLM_OPENAI_ENDPOINT |
OPENAI_DEPLOYMENT_NAME | LLM_OPENAI_DEPLOYMENT |
OPENAI_API_VERSION | LLM_OPENAI_API_VERSION |
GOOGLE_API_KEY | LLM_GOOGLE_API_KEY |
GOOGLE_API_ENDPOINT | (removed) |
AWS_BEDROCK_EMBED_MODEL_ID, AWS_BEDROCK_EMBEDDING_DIMENSION, OPENAI_EMBEDDING_MODEL_ID, OPENAI_EMBEDDING_DIMENSION, GOOGLE_EMBEDDING_MODEL_ID, GOOGLE_EMBEDDING_DIMENSION, DJL_EMBEDDING_MODEL, EMBEDDING_PROVIDER and MAX_CONCURRENT_EMBEDDING_REQUESTS keep their names but move under llmConfiguration.embeddings.
Bedrock IAM auth now defaults to enabled
BEDROCK_AWS_IAM_AUTH_ENABLED flips from false to true. Deployments that relied on the default being off, and supplied static keys, should confirm which credential chain is used.
Action
Port your NLQ/embedding configuration into llmConfiguration before upgrading. Semantic search silently degrades (provider resolves to noop) rather than failing loudly if the block is missing.
Session management¶
Sessions are database-backed¶
Behavioural · Affects: multi-pod deployments
2.0 adds a user_session table so sessions survive pod restarts and are shared across pods. Previously each pod held its own in-memory session state, which caused spurious logouts behind a load balancer without sticky sessions.
Columns: id, userId, status, expiresAt, idleExpiresAt, updatedAt, sessionType, provider, version, lastAccessedAt, refreshLeaseUntil, plus the session JSON.
Concurrent sessions are capped per user¶
Behavioural — users will be logged out
authenticationConfiguration:
sessionExpiry: ${AUTHENTICATION_SESSION_EXPIRY:-"604800"} # 7 days, all auth providers
maxActiveSessionsPerUser: ${AUTHENTICATION_MAX_ACTIVE_SESSIONS_PER_USER:-5}
Maximum number of active authenticated sessions allowed per user. When the limit is exceeded, the least recently used active sessions are revoked. If unset, OpenMetadata uses the default of 5.
sessionExpiry now applies to all auth providers (minimum 3600 s). oidcConfiguration.sessionExpiry becomes a deprecated fallback.
Who this affects
Users who work across several browsers/devices, and service accounts or shared users driving many concurrent sessions, will start being silently signed out of the oldest sessions. Raise AUTHENTICATION_MAX_ACTIVE_SESSIONS_PER_USER if that is your pattern — but prefer bot tokens for automation.
Additional trusted redirect URIs¶
Allows redirect URIs beyond callbackUrl and the server's own callbacks — each entry must match the requested URI exactly (scheme, host, port, path, query). Intended for browser-extension logins, e.g. https://<extension-id>.chromiumapp.org/auth0.
Related SSO hardening in 2.0: the server /auth/callback is trusted in the SAML redirect allowlist, SAML pending-session ids are carried in RelayState, and the OIDC login-loop is hardened with an interactive fallback on login_required that preserves pending logins.
Admin test-login¶
Validates a browser-obtained OIDC id_token against a candidate (unsaved) security configuration, so an admin can confirm a real login resolves the expected identity before saving. Schemas: system/testLoginTokenRequest.json, system/testLoginResult.json.
LDAP¶
recursiveGroupMembership (default false) enables transitive group resolution for Active Directory nested groups via LDAP_MATCHING_RULE_IN_CHAIN.
Database connection timeouts changed¶
Behavioural — long-running queries will now be cut off
| Setting | 1.13 | 2.0 |
|---|---|---|
database.queryTimeoutSeconds | — | 300 (new, DB_QUERY_TIMEOUT_SECONDS) |
Postgres loginTimeout (s) | 300 | 30 |
Postgres postgresqlConnectTimeout (s) | 60 | 30 |
Postgres postgresqlSocketTimeout (s) | 30000 (≈8.3 h) | 300 (5 min) |
MySQL mysqlSocketTimeout (ms) | 30000000 (≈8.3 h) | 300000 (5 min) |
Five-minute ceiling on statements
Any query that previously ran for more than five minutes — a large reindex batch, a heavy Data Insights aggregation, an oversized CSV import — now aborts. Raise DB_QUERY_TIMEOUT_SECONDS, DB_POSTGRESQL_SOCKET_TIMEOUT or DB_MYSQL_SOCKET_TIMEOUT if you have legitimately long statements, and check upgrade logs for statement-timeout errors.
Server & logging configuration¶
HTTP/2 is available (opt-in)¶
server:
applicationConnectors:
- type: ${SERVER_PROTOCOL:-http} # http (default) | h2c (cleartext HTTP/2) | h2 (TLS)
dropwizard-http2 is on the classpath, so h2c and h2 connector types work out of the box. Both are backwards compatible — HTTP/1.1 clients keep working on the same port. Worth enabling when browsers hit Jetty directly (Docker Compose, on-prem single node); not worth it behind an HTTP/2-terminating load balancer.
Response compression enabled¶
server.gzip.enabled is true and the comment changes from "Response compression disabled for maximum throughput" to a description of Jetty's GzipHandler. Responses above ~256 bytes are now gzipped. Clients that mishandle Content-Encoding: gzip — rare, but possible in hand-rolled HTTP code — will need Accept-Encoding: identity.
Logging hardening¶
Security-relevant
logging:
loggers:
org.eclipse.jetty:
level: ${JETTY_LOG_LEVEL:-INFO}
org.openmetadata.service.audit.AuditLogRepository:
level: INFO
appenders:
- type: console
filterFactories:
- type: audit-exclude-filter-factory
LOG_LEVEL sets the root logger, and at DEBUG Jetty's HttpParser prints every request header verbatim — including Authorization: Bearer <jwt> and Cookie: OM_SESSION=<id>. Since DEBUG is exactly what support asks customers to enable, and those logs get attached to tickets, the Jetty logger is now pinned independently via JETTY_LOG_LEVEL.
Audit entries are logged at INFO with an AUDIT marker and routed to logs/audit.log; the level is pinned so audit capture does not depend on the global LOG_LEVEL, and an audit-exclude-filter-factory keeps them out of the console appender.
Action
If you parsed audit entries out of stdout, read logs/audit.log instead. If you need Jetty debug output, set JETTY_LOG_LEVEL=DEBUG explicitly — and be aware of what it prints.
Object storage configuration expanded¶
· Affects: deployments using file attachments
objectStorage:
- enabled: false
- provider: NOOP
- maxFileSize: 5242880
+ enabled: ${ASSET_UPLOADER_ENABLE:-false}
+ provider: ${ASSET_UPLOADER_PROVIDER:-s3} # s3 | azure | inmemory
+ maxFileSize: ${ASSET_UPLOADER_MAX_FILE_SIZE:-5242880}
+ s3: { endpoint, bucketName, region, accessKey, secretKey, useIamRole, iamRoleArn,
+ prefixPath, sseAlgorithm, kmsKeyId }
+ azure: { containerName, connectionString, useManagedIdentity, clientId, tenantId,
+ clientSecret, blobEndpoint, prefixPath }
The default provider changes from NOOP to s3 — but enabled still defaults to false, so nothing activates until you turn it on. This backs the new /v1/attachments API (uploaded assets for Context Center files, Knowledge Center pages and cover images). For MinIO, use provider s3 and point s3.endpoint at the MinIO server.
Query timeouts and workflow polling¶
See Data Governance → Workflows fire far sooner for the Flowable interval changes, which raise steady-state database polling.
Ingestion pipeline client¶
pipelineServiceClientConfiguration gains queuedStatusTimeoutSeconds (default 3600) — how long a queued status stays visible before being treated as stale and hidden. Covers runs an orchestrator accepted but never started.
The 2.0.0 database migration¶
Plan a maintenance window
New tables¶
| Table | Purpose |
|---|---|
task_entity, new_task_sequence, task_migration_mapping | Task redesign |
task_form_schema_entity | Task form schemas |
announcement_entity | Standalone announcements |
activity_stream (partitioned), activity_stream_config | Activity stream |
background_job_logs | Background job logs |
search_index_job, search_index_retry_queue | Distributed reindexing |
user_session | DB-backed sessions |
user_preferences | App-managed per-user preferences (no FK; cascade-deleted via UserRepository#postDelete) |
knowledge_center, drive_folder, context_file, context_file_content, context_memory, asset_entity | Knowledge / Context Center + attachments |
ai_governance_framework_entity, ai_framework_control_entity, audit_report_entity | AI Governance Studio |
Altered tables¶
background_jobs— addsprogress,total,result,error,message,cancelRequested,completedAttag_usage— addsmetadata JSONaudit_log_event— addssearch_text LONGTEXTthread_entity→ renamed tothread_entity_legacy
Data migrations¶
| Step | Effect |
|---|---|
migrateSuggestionsToTaskEntity | suggestions → task_entity |
migrateThreadTasksToTaskEntity | thread tasks → task_entity (+ task_migration_mapping) |
migrateLegacyActivityThreadsToActivityStream | generated feed threads → activity_stream |
Announcement INSERT … SELECT | thread_entity → announcement_entity |
backfillAnnouncementRelationships | Announcement ↔ entity relationships |
backfillSearchRankingSettings + SearchIndexSettingsRepair | Staged ranking config into searchSettings |
addTableColumnSearchSettings | Column search settings |
migrateRdfIndexAppScheduleToWeekly | RDF app cadence |
addTaskAuthorPolicyToDataConsumerRole and three sibling policy steps | Task permissions |
TaskWorkflow.runTaskWorkflowCutoverMigration / addTaskResourceToMentionAlerts / runRecognizerFeedbackTaskTypeMigration | Workflow + alert cutover |
| SQL rewrites | Databricks Pipeline authType, Snowflake/Databricks/UnityCatalog policyAgentConfig, Postgres policyAgentConfig removal, app runtime-field stripping, DataInsights dataQuality removal, McpApplication config removal, AutoClassificationBotPolicy Topic rule, CvvRecognizer regex anchor, stale pipelineStatuses cleanup |
Index additions¶
Many, including (deleted, name) and (deleted, serviceType) composites on all 13 service tables (for /v1/services/overview), name indexes on the new entity tables (so the distributed reindex cursor runs index-only instead of a filesort that can exhaust sort memory on large tables), and idx_wf_instance_state_execution_id on workflow_instance_state_time_series.
Index creation on large tables
On clusters with tens of millions of rows, the composite index creation on service and entity tables is the long pole of the migration. Size your maintenance window accordingly.
Dependency and CVE updates¶
— not breaking, but relevant to hardened deployments.
Backend: Jetty 12.1.7 → 12.1.10 (with jetty-bom imported so transitive modules follow), Netty 4.1.137.Final, BouncyCastle 1.85, jackson-databind 2.18.8, tools.jackson BOM 3.1.5, log4j 2.25.5, libthrift/thrift 0.24.0, reactor-netty-http 1.2.18, tomcat-jdbc/juli 11.0.11, httpcore5 5.4.3, Redshift JDBC 2.1.0.30 → 2.2.2, Kubernetes client-java 25.0.1, Apache Airflow 3.3.0 on Python 3.12.
Frontend: ws 8.21.0, handlebars 4.5.2, js-yaml 5.2.2, fast-uri 3.1.5, nanoid 3.3.17, brace-expansion 1.1.18 / 5.0.9.
Ingestion images: apt package trimming for gnutls, libcap, openssh, rsync, util-linux and the Go CVE surface; mlflow-skinny and pyarrow bumped.
Other security fixes worth noting operationally:
- Test-connection workflow triggers are authorized.
- CSRF failures fail-secure and retry on the next request instead of permanently breaking.
POST .../testDestinationredacts destination config from the response.- SCIM
displayNamesync is fixed (a bot-PUT guard was reverting it).