[Proposal] Gateway Controller DB Schema — Per-Resource-Type Tables #1311
Replies: 2 comments 2 replies
-
When there are many APIs, will this runtime parsing cause any slowness during startup? (In other words, is there a need to store any processed entities in DB? If there is no issue in startup, its okay to avoid this.)
+1 to the overal proposal. |
Beta Was this translation helpful? Give feedback.
-
|
+1 for the proposal. The status filed in artifacts, will no longer have failed or pending. It will be always the desired state. Shall we rename that as well to |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Summary
Refactor the gateway controller's database schema from a flat two-table design (
deployments+deployment_configs) into a baseartifactstable with per-resource-type child tables, following the same pattern already used by Platform API. Key changes:deployments→artifactsas the shared base table for all resource typesdeployment_configstable with 5 type-specific tables:rest_apis,websub_apis,llm_providers,llm_proxies,mcp_proxiesapi.APIConfigurationis regenerated at load time via the existing Transformer pipelineid→uuidacross all tables for consistency with Platform APIgateway_iddefault from'platform-gateway-id'to'default'contextcolumn (no longer unique — multiple resources (Artifacts) can share the same context path)deployed_versioncolumn (derived xDS state, never queried from DB)Motivation
1. All resource types share a single table
Today, REST APIs, LLM providers, LLM proxies, MCP proxies, and WebSub APIs all live in the same
deploymentstable, distinguished only by akindcolumn. Thedeployment_configstable stores their configuration as a JSON blob with two columns:This makes it impossible to:
llm_proxies.provider_uuidcan be a proper FK withON DELETE RESTRICT, preventing deletion of a provider that still has proxies depending on it.2. Redundant configuration storage
Both
configuration(the derivedapi.APIConfiguration) andsource_configuration(the original typed config) are persisted. But the derived config is always regeneratable from the source config via the existing Transformer pipeline:api.APIConfigurationapi.APIConfigurationLLMProviderConfigurationAPIConfigurationLLMProxyConfigurationAPIConfigurationMCPProxyConfigurationAPIConfigurationStoring the derived config wastes space and creates a sync risk if the transformation logic changes.
3. Incorrect unique constraints
The current constraints don't account for resource kind:
A RestApi named "my-service" and an LlmProvider named "my-service" are different resources and should be allowed to coexist.
4. Unnecessary columns
context: Was used for conflict detection (unique context paths). Context is no longer unique — multiple resources can share the same context path. The value already lives in the configuration JSON.deployed_version: Tracks the xDS snapshot version a config was last deployed under. This is derived state managed in-memory by the xDS server — it's written to DB but never queried or used for any business logic.5. Inconsistent naming
idin gateway controller butuuidin Platform APIgateway_iddefaults to'platform-gateway-id'which is oddly specificapi_keys.apiIduses camelCase while all other columns use snake_caseProposed Design
Target Schema
Removed tables:
deployment_configsRemoved columns:
context,deployed_versionReferential integrity via
ON DELETEstrategy:rest_apis.uuid → artifactsCASCADEllm_proxies.uuid → artifactsCASCADEllm_proxies.provider_uuid → llm_providersRESTRICTapi_keys.artifact_uuid → artifactsCASCADEOther table renames:
certificates.id→certificates.uuidllm_provider_templates.id→llm_provider_templates.uuidapi_keys.id→api_keys.uuidapi_keys.apiId→api_keys.artifact_uuid(FK →artifacts(uuid))gateway_iddefaults changed to'default'Data Flow Changes
Write path (create/update):
api.APIConfiguration(for in-memory use)artifactsStoredConfig(with both source and derived) to in-memory ConfigStoreRead path (startup loader):
GetAllConfigs()reads fromartifactsJOIN type tablesapi.APIConfiguration— unmarshal directlyapi.APIConfigurationRead path (REST handlers — unchanged):
GetAPIById: Returnscfg.Configurationfrom in-memory cache (or DB for RestApi)GetLLMProviderById: Returnscfg.SourceConfigurationfrom in-memory cacheSQL Query Strategy
Single-record reads (
GetConfig,GetConfigByHandle,GetConfigByNameVersion):Two-step approach — query
artifactsfor base record (includingkind), then query the correct type table.Bulk reads (
GetAllConfigs):UNION ALL across all 5 type tables joined with
artifacts.Kind-filtered reads (
GetAllConfigsByKind):Single JOIN between
artifactsand the one relevant type table.Writes: Insert into
artifacts+ correct type table in a transaction.Deletes: Delete from
artifacts— CASCADE handles the type table row.What Does NOT Change
models.StoredConfigstruct — keeps bothConfigurationandSourceConfigurationfields. They're populated differently (DB returns source only; create/update populates both in memory).Storageinterface — generic methods (SaveConfig,GetConfig, etc.) stay unchangedConfigStore(in-memory cache) — unchangedStoredConfigfrom in-memory cache, unaffectedMigration
deployment_configsto the correct type table per kind, dropsdeployment_configs.ALTER TABLE RENAME,INSERT...SELECTfor data migration.Alignment with Platform API
This brings the gateway controller schema in line with Platform API's existing pattern:
artifactsartifactsuuid VARCHAR(40)uuid TEXTrest_apis,llm_providers,llm_proxiesrest_apis,websub_apis,llm_providers,llm_proxies,mcp_proxiesconfiguration TEXTin type tableconfiguration TEXTin type tableUNIQUE(name, version, organization_uuid)UNIQUE(gateway_id, kind, display_name, version)Beta Was this translation helpful? Give feedback.
All reactions