docs(rfc): Settings Service — hierarchical runtime configuration - #7775
Conversation
Proposes implementing the already-merged flyteidl2/settings IDL (#7127): org/domain/project-scoped typed settings with inheritance, phased into small independent tasks for parallel contribution. Claude-Session: https://claude.ai/code/session_015eKZQGuUBZ5PaRmHp6PdFH Signed-off-by: Kevin Su <pingsutw@apache.org>
Claude-Session: https://claude.ai/code/session_015eKZQGuUBZ5PaRmHp6PdFH Signed-off-by: Kevin Su <pingsutw@apache.org>
There was a problem hiding this comment.
Pull request overview
Adds an RFC document proposing a server-side implementation of Flyte 2’s existing (already-merged) strongly-typed Settings API, describing motivation, inheritance semantics, storage approach, resolution/validation logic, service wiring, and a phased delivery plan.
Changes:
- Introduces a new RFC detailing hierarchical org/domain/project runtime configuration via
SettingsService. - Documents scope inheritance rules (
INHERIT/VALUE/UNSET) with concrete examples for env vars, resource guardrails, and queue routing. - Outlines an incremental implementation plan (persistence → resolution/service → run-path application → user surfaces) with pointers to in-repo patterns.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Claude-Session: https://claude.ai/code/session_015eKZQGuUBZ5PaRmHp6PdFH Signed-off-by: Kevin Su <pingsutw@apache.org>
Claude-Session: https://claude.ai/code/session_015eKZQGuUBZ5PaRmHp6PdFH Signed-off-by: Kevin Su <pingsutw@apache.org>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.
Suppressed comments (1)
docs/rfcs/7775-settings-service.md:199
- The RFC proposes a text key format
"v1:{org}:{domain}:{project}", but (perflyteidl2/common/identifier.proto) domain/project identifiers are not constrained to exclude:. Without either escaping or an explicit restriction,:inside a segment would make the encoding ambiguous and hard to parse reliably. Consider specifying/validating a delimiter-safe encoding (e.g., URL-escape segments) or explicitly rejecting:in org/domain/project at the API boundary.
Validation is hand-written in the service (the generated `Validate()` from
protoc-gen-validate does not enforce the `buf.validate` annotations used in
the settings protos): key shape (org required; project requires domain),
quantities parse via `resource.ParseQuantity`, and
OSS has no organization concept; normalize empty SettingsKey.org to
secret.DefaultOrganization ("flyte"), matching the secret and app
services. Org-level settings become instance-wide defaults.
Claude-Session: https://claude.ai/code/session_015eKZQGuUBZ5PaRmHp6PdFH
Signed-off-by: Kevin Su <pingsutw@apache.org>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.
Suppressed comments (1)
docs/rfcs/7775-settings-service.md:172
- For consistency with existing
runs/migrations/sql/*.sql(e.g.runs/migrations/sql/20260408110000_init_schema.sqlusesDEFAULT CURRENT_TIMESTAMP), consider usingCURRENT_TIMESTAMPinstead ofNOW()in this schema example so future migrations follow the established pattern.
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
Flyte 2 runs all task pods in one namespace, so v1's implicit per-project-domain PodTemplate (via per-namespace resources) no longer works. Propose a pod_template_name StringSetting: resolved per scope, stamped onto tasks without an explicit template, looked up by the existing PodTemplateStore. Claude-Session: https://claude.ai/code/session_015eKZQGuUBZ5PaRmHp6PdFH Signed-off-by: Kevin Su <pingsutw@apache.org>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.
Suppressed comments (1)
docs/rfcs/7775-settings-service.md:232
- The validation bound uses
MaxUint32but the doc doesn’t explain why that upper limit exists. Since the setting is later applied toRunSpec.max_action_concurrency(auint32inflyteidl2/task/run.proto), it would be clearer to either cite that type constraint or spell out the numeric upper bound so readers don’t have to infer it.
`max_action_concurrency` ∈ {0} ∪ [2, MaxUint32] (a cap of 1 would deadlock
any run with more than one action).
Claude-Session: https://claude.ai/code/session_015eKZQGuUBZ5PaRmHp6PdFH Signed-off-by: Kevin Su <pingsutw@apache.org>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.
Suppressed comments (1)
docs/rfcs/20260804_settings_service.md:180
- This section says OSS clients can omit
organd rely on server-side normalization, butSettingsKey.orginflyteidl2/settings/settings_definition.protois annotated with(buf.validate.field).string.min_len = 1, so clients (or future server middleware) that enforcebuf.validatewill reject an empty org. The RFC should either propose loosening that IDL constraint, or clarify that OSS clients should still send the placeholder org ("flyte").
**Org handling in OSS.** OSS deployments have no organization concept, so an
empty `org` is normalized server-side to the existing placeholder
`DefaultOrganization = "flyte"`
(`flyteplugins/go/tasks/pluginmachinery/secret/embedded_secret_manager.go`) —
the same convention the secret and app services already use. Org-level
Claude-Session: https://claude.ai/code/session_015eKZQGuUBZ5PaRmHp6PdFH Signed-off-by: Kevin Su <pingsutw@apache.org>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.
Suppressed comments (1)
docs/rfcs/20260804_settings_service.md:177
- This section says OSS clients never need to send an org and can send an empty
orgthat the server normalizes to"flyte", but the IDL currently declaresSettingsKey.orgwith(buf.validate.field).string.min_len = 1(seeflyteidl2/settings/settings_definition.proto:74). Even if the server chooses to accept empty orgs, the RFC should acknowledge this mismatch (or recommend clients send"flyte"explicitly) to avoid surprising client / gateway-side validation failures.
`DefaultOrganization = "flyte"`
(`flyteplugins/go/tasks/pluginmachinery/secret/embedded_secret_manager.go`) —
the same convention the secret and app services already use. Org-level
settings therefore act as **instance-wide defaults**; clients never need to
send an org.
OSS has no org concept; keep 'org' only where the wire format and storage key require it, with the default-org normalization note. Claude-Session: https://claude.ai/code/session_015eKZQGuUBZ5PaRmHp6PdFH Signed-off-by: Kevin Su <pingsutw@apache.org>
flyte-sdk already supports editing settings, so phase 4 is end-to-end verification plus docs; no UI work. Remove the Alternatives section. Claude-Session: https://claude.ai/code/session_015eKZQGuUBZ5PaRmHp6PdFH Signed-off-by: Kevin Su <pingsutw@apache.org>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.
Suppressed comments (2)
docs/rfcs/20260804_settings_service.md:199
- The optimistic-locking UPDATE example only increments
version; as written it doesn’t mention updatingupdated_at, which would otherwise remain at its insert-time value unless the repository layer explicitly sets it. Clarifying this in the RFC will avoid implementers copying an UPDATE that never bumpsupdated_at.
- `version` implements optimistic locking: `UPDATE ... SET version = version + 1
WHERE key = $1 AND version = $2`; zero rows affected ⇒ the caller loses the
race and must re-read (same pattern as the existing trigger repository).
docs/rfcs/20260804_settings_service.md:164
- In the IDL (
flyteidl2/settings/settings_service.proto) the RPC is described as an upsert, but here it’s described only as an optimistic-locking update. Since the version field is required for updates (and the customer-flow doc indicates Create vs Update depending on record existence), it would help to explicitly state whether UpdateSettings is expected to fail when the record doesn’t exist vs support a create-on-missing path and what version should be used in that case.
service SettingsService {
rpc GetSettings(GetSettingsRequest) returns (GetSettingsResponse); // merged, effective values
rpc GetSettingsForEdit(GetSettingsForEditRequest) returns (GetSettingsForEditResponse); // unmerged, one record per scope level
rpc CreateSettings(CreateSettingsRequest) returns (CreateSettingsResponse);
rpc UpdateSettings(UpdateSettingsRequest) returns (UpdateSettingsResponse); // optimistic locking via version
}
Claude-Session: https://claude.ai/code/session_015eKZQGuUBZ5PaRmHp6PdFH Signed-off-by: Kevin Su <pingsutw@apache.org>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.
Suppressed comments (1)
docs/rfcs/20260804_settings_service.md:228
- The motivation for rejecting
max_action_concurrency = 1is described as a “deadlock”, but with a simple concurrency cap a value of 1 would typically just serialize action execution (slow), not deadlock. This reads as inaccurate and could mislead future implementers/readers; consider rephrasing the rationale while keeping the proposed bounds clear (also makes the negative/invalid-case handling more explicit).
the settings protos): key shape (empty org defaults to `"flyte"`; project
requires domain),
quantities parse via `resource.ParseQuantity`, and
`max_action_concurrency` ∈ {0} ∪ [2, MaxUint32] (a cap of 1 would deadlock
any run with more than one action).
|
This makes sense to me. |
|
I'm currently implementing 2.3 Validator, and wanted to check the reasoning behind the bounds.
|
Why
The settings API (
flyteidl2/settings/settings_service.proto,settings_definition.proto) was designed, reviewed, and merged in #7127 — with generated clients for Go, TypeScript, Python, and Rust — but no server implements it yet. This RFC proposes implementing theSettingsService: instance/domain/project-scoped, strongly-typed runtime configuration (default queue, task resource guardrails, env vars, labels/annotations, service account, storage paths) with well-defined inheritance semantics.What this RFC covers
UNSETblocking inheritance.The existing walkthrough doc
flyteidl2/settings/settings_customer_flow.mddoubles as the acceptance-test spec: Phase 2 is done when every example in it reproduces against a running server.The only proto change proposed is a single new
pod_template_nameStringSetting (restores per-project/domain PodTemplate selection, which single-namespace Flyte 2 lost); everything else is server/consumer implementation work.