Skip to content

[ENH]: Config to enable quantization on tenants#6297

Merged
sanketkedia merged 3 commits intomainfrom
01-31-_enh_config_to_enable_quantization_on_tenants
Feb 3, 2026
Merged

[ENH]: Config to enable quantization on tenants#6297
sanketkedia merged 3 commits intomainfrom
01-31-_enh_config_to_enable_quantization_on_tenants

Conversation

@sanketkedia
Copy link
Copy Markdown
Contributor

@sanketkedia sanketkedia commented Jan 31, 2026

Description of changes

Summarize the changes made by this PR.

  • Improvements & Bug fixes
    • Adds a frontend config that gives ability to specify tenants for which quantization needs to be set to true. There is a also a support to specify * which enables quantization for all tenants
  • New functionality
    • ...

Test plan

How are these changes tested?

  • Tests pass locally with pytest for python, yarn test for js, cargo test for rust

Migration plan

None

Observability plan

None

Documentation Changes

None

Copy link
Copy Markdown
Contributor Author

sanketkedia commented Jan 31, 2026

@github-actions
Copy link
Copy Markdown

Reviewer Checklist

Please leverage this checklist to ensure your code review is thorough before approving

Testing, Bugs, Errors, Logs, Documentation

  • Can you think of any use case in which the code does not behave as intended? Have they been tested?
  • Can you think of any inputs or external events that could break the code? Is user input validated and safe? Have they been tested?
  • If appropriate, are there adequate property based tests?
  • If appropriate, are there adequate unit tests?
  • Should any logging, debugging, tracing information be added or removed?
  • Are error messages user-friendly?
  • Have all documentation changes needed been made?
  • Have all non-obvious changes been commented?

System Compatibility

  • Are there any potential impacts on other parts of the system or backward compatibility?
  • Does this change intersect with any items on our roadmap, and if so, is there a plan for fitting them together?

Quality

  • Is this code of a unexpectedly high quality (Readability, Modularity, Intuitiveness)

@sanketkedia sanketkedia marked this pull request as ready for review January 31, 2026 22:05
@propel-code-bot
Copy link
Copy Markdown
Contributor

propel-code-bot bot commented Jan 31, 2026

Tenant-scoped quantization toggle with schema safeguards

Introduces a frontend configuration flag (tenants_with_quantization_enabled) that lets operators selectively enable SPANN quantization for specific tenants (or all via "*"). The service layer now inspects this list when creating collections, mutates the reconciled schema via the new Schema::get_spann_config_mut, and chooses quantized SPANN segments accordingly; schema merging was tightened to reject user-provided quantize=true and comprehensive unit/property tests were added.
Sample distributed configs include the new knob (defaulting to an empty list) and Python bindings/front-end config constructors now surface it. Additional schema helpers/validations were added to ensure failures surface early when user input attempts to flip quantization outside the sanctioned configuration path.

Key Changes

• Added tenants_with_quantization_enabled to FrontendConfig, sample YAMLs, Python bindings, and plumbed it through ServiceBasedFrontend to flip SpannIndexConfig.quantize during collection creation
• Extended Schema with get_spann_config_mut, made vector/SPANN merge helpers fallible, and enforced that user/default schemas cannot set quantize=true; added property/unit tests (including error cases) to validate the behavior
• Updated schema reconciliation paths to propagate errors from merge helpers and added runtime selection of SegmentType::QuantizedSpann when quantization is enabled

Affected Areas

• rust/types/src/collection_schema.rs
• rust/frontend/src/config.rs
• rust/frontend/src/impls/service_based_frontend.rs
• rust/frontend/sample_configs/*.yaml
• rust/python_bindings/src/bindings.rs

This summary was automatically generated by @propel-code-bot

@sanketkedia sanketkedia force-pushed the 01-30-_enh_create_new_vector_segment_type_based_on_config branch from 0dfe648 to afa75d2 Compare January 31, 2026 22:13
@sanketkedia sanketkedia force-pushed the 01-31-_enh_config_to_enable_quantization_on_tenants branch from 68bcf60 to 920cbc1 Compare January 31, 2026 22:13
/// - The tenant_id is in the list
fn should_enable_quantization_for_tenant(&self, tenant_id: &str) -> bool {
self.tenants_with_quantization_enabled
.contains(&"*".to_string())
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: would prefer a separate config flag if possible

@sanketkedia sanketkedia force-pushed the 01-30-_enh_create_new_vector_segment_type_based_on_config branch 2 times, most recently from cb0819a to 6a1d588 Compare February 3, 2026 02:16
@sanketkedia sanketkedia force-pushed the 01-31-_enh_config_to_enable_quantization_on_tenants branch from 920cbc1 to bf56c81 Compare February 3, 2026 02:16
tenants_to_migrate_immediately_threshold: None,
enable_schema,
min_records_for_invocation: default_min_records_for_invocation(),
tenants_with_quantization_enabled: vec![],
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Important

[Logic] Hardcoding an empty list here will forcibly disable quantization for all local Python users (setting quantize=false in the schema), even if they explicitly enable it in their collection configuration. This makes it impossible to test or use the feature locally.

Consider defaulting to vec!["*".to_string()] for local bindings to allow usage, or exposing this as a configuration parameter.

Context for Agents
Hardcoding an empty list here will forcibly disable quantization for all local Python users (setting `quantize=false` in the schema), even if they explicitly enable it in their collection configuration. This makes it impossible to test or use the feature locally.

Consider defaulting to `vec!["*".to_string()]` for local bindings to allow usage, or exposing this as a configuration parameter.

File: rust/python_bindings/src/bindings.rs
Line: 132

@sanketkedia sanketkedia changed the base branch from 01-30-_enh_create_new_vector_segment_type_based_on_config to graphite-base/6297 February 3, 2026 02:54
@sanketkedia sanketkedia force-pushed the 01-31-_enh_config_to_enable_quantization_on_tenants branch from bf56c81 to e73a5eb Compare February 3, 2026 02:54
@graphite-app graphite-app bot changed the base branch from graphite-base/6297 to main February 3, 2026 02:55
@sanketkedia sanketkedia force-pushed the 01-31-_enh_config_to_enable_quantization_on_tenants branch from e73a5eb to 927575d Compare February 3, 2026 02:55
@sanketkedia sanketkedia force-pushed the 01-31-_enh_config_to_enable_quantization_on_tenants branch from 927575d to cbe97d7 Compare February 3, 2026 03:19
Comment on lines 546 to +555
None
};

// Enable quantization for tenants in the config list (or all tenants if "*" is present)
if let Some(ref mut schema) = reconciled_schema {
if let Some(spann_config) = schema.get_spann_config_mut() {
spann_config.quantize = self.should_enable_quantization_for_tenant(&tenant_id);
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Important

[Reliability] Enabling quantization now unconditionally flips schema.get_spann_config_mut().quantize and later forces SegmentType::QuantizedSpann (around line 597) whenever the tenant matches. However, we never verify that the active executor actually advertises support for quantized segments – the capability check above (if !supported_segment_types.contains(Spann) && !supported_segment_types.contains(QuantizedSpann)) only ensures one of those types exists. In environments where the backend only supports plain SPANN (which was fine before this PR), turning on the new knob will push an unsupported SegmentType::QuantizedSpann into sysdb, and the executor will fail the collection creation at runtime.

Before toggling quantize/selecting SegmentType::QuantizedSpann, guard on supported_segment_types.contains(&SegmentType::QuantizedSpann) (or return a clear error/fall back to non-quantized SPANN). For example:

Suggested change
None
};
// Enable quantization for tenants in the config list (or all tenants if "*" is present)
if let Some(ref mut schema) = reconciled_schema {
if let Some(spann_config) = schema.get_spann_config_mut() {
spann_config.quantize = self.should_enable_quantization_for_tenant(&tenant_id);
}
}
let enable_quantization = self.should_enable_quantization_for_tenant(&tenant_id);
if enable_quantization && !supported_segment_types.contains(&SegmentType::QuantizedSpann) {
return Err(CreateCollectionError::SpannNotImplemented);
}
if let Some(ref mut schema) = reconciled_schema {
if let Some(spann_config) = schema.get_spann_config_mut() {
spann_config.quantize = enable_quantization;
}
}

This keeps legacy deployments (without quantized SPANN support) from attempting to create unsupported segments while still enabling the feature where it’s available.

Context for Agents
Enabling quantization now unconditionally flips `schema.get_spann_config_mut().quantize` and later forces `SegmentType::QuantizedSpann` (around line 597) whenever the tenant matches. However, we never verify that the active executor actually advertises support for quantized segments – the capability check above (`if !supported_segment_types.contains(Spann) && !supported_segment_types.contains(QuantizedSpann)`) only ensures *one* of those types exists. In environments where the backend only supports plain SPANN (which was fine before this PR), turning on the new knob will push an unsupported `SegmentType::QuantizedSpann` into sysdb, and the executor will fail the collection creation at runtime.

Before toggling `quantize`/selecting `SegmentType::QuantizedSpann`, guard on `supported_segment_types.contains(&SegmentType::QuantizedSpann)` (or return a clear error/fall back to non-quantized SPANN). For example:
```suggestion
        let enable_quantization = self.should_enable_quantization_for_tenant(&tenant_id);
        if enable_quantization && !supported_segment_types.contains(&SegmentType::QuantizedSpann) {
            return Err(CreateCollectionError::SpannNotImplemented);
        }

        if let Some(ref mut schema) = reconciled_schema {
            if let Some(spann_config) = schema.get_spann_config_mut() {
                spann_config.quantize = enable_quantization;
            }
        }
```
This keeps legacy deployments (without quantized SPANN support) from attempting to create unsupported segments while still enabling the feature where it’s available.

File: rust/frontend/src/impls/service_based_frontend.rs
Line: 555

(None, None) => None,
(Some(default), Some(user)) => {
// Validate that quantize is always false (should only be set programmatically by frontend)
if user.quantize || default.quantize {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Critical

[Logic] The validation logic here (if user.quantize || default.quantize) combined with forcing quantize: false (line 1650) creates a critical issue for the read path.

When a collection is created, ServiceBasedFrontend::create_collection sets quantize = true in the schema and persists it to SysDB. When this collection is later retrieved via get_collection, reconcile_schema_for_read() calls reconcile_with_defaults(), which invokes this merge logic.

  1. The validation check will fail because the persisted schema (treated as user) has quantize: true, causing get_collection to return an error.
  2. Even if the validation passed, line 1650 forces quantize: false in the result, effectively disabling quantization in the loaded schema object, which creates a mismatch with the actual segments.

Fix:

  1. Remove the validation from merge_spann_configs (or scope it only to user input validation phase).
  2. Preserve the quantize value from the user (source) schema instead of hardcoding false.
Context for Agents
The validation logic here (`if user.quantize || default.quantize`) combined with forcing `quantize: false` (line 1650) creates a critical issue for the read path.

When a collection is created, `ServiceBasedFrontend::create_collection` sets `quantize = true` in the schema and persists it to SysDB. When this collection is later retrieved via `get_collection`, `reconcile_schema_for_read()` calls `reconcile_with_defaults()`, which invokes this merge logic.

1. The validation check will fail because the persisted schema (treated as `user`) has `quantize: true`, causing `get_collection` to return an error.
2. Even if the validation passed, line 1650 forces `quantize: false` in the result, effectively disabling quantization in the loaded schema object, which creates a mismatch with the actual segments.

**Fix:** 
1. Remove the validation from `merge_spann_configs` (or scope it only to user input validation phase).
2. Preserve the `quantize` value from the `user` (source) schema instead of hardcoding `false`.

File: rust/types/src/collection_schema.rs
Line: 1624

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reconcile_schema_for_read does not call reconcile_with_defaults

@sanketkedia sanketkedia enabled auto-merge (squash) February 3, 2026 03:42
@sanketkedia sanketkedia merged commit d2f353f into main Feb 3, 2026
68 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants