Service-Per-Business-Unit in Cortex Search Buys Real Availability and Throughput Containment, and Buys Leakage Containment Only If the Grant Graph Partitions Too
The question
"At a Fortune-2000 client-intelligence scale, does blast-radius containment argue for multiple Cortex Search services (service-per-business-unit) vs one mega-index, even within a flat shared-internal model?"
Promoted from the open follow-ups of the 2026-06-17 multi-tenant governance brief, which locked "flat internal, hard-walled external" for the client-intelligence plane and then asked whether that flat model should still be physically partitioned at the retrieval layer. Direct bearing on phData Data Solutions Architect / Forward Deployed Engineer delivery work.
What we already know (from the vault)
- [[2026-06-17-multi-tenant-governance-shared-vector-store]] — the parent brief. Locked position: shared store is fine for the internal plane, the isolation budget concentrates at the external demo boundary, and the governing principle is "enforce isolation in the data layer, never the LLM." It reached that principle via Cortex Agents multi-tenancy (immutable session attributes plus row access policies). This brief finds that the principle survives but the mechanism does not transfer to Cortex Search.
- [[2026-04-28-snowflake-enterprise-knowledge-management]] — already asserts the answer flatly: "Cortex Search per business unit (not one giant index) for blast-radius containment... Most clients will get this wrong by indexing everything into one mega-service and discovering at audit time they can't prove who saw what." That brief cited no limit, cost figure, or grant semantics to support it. It also recorded the practitioner finding that default Cortex RBAC is "service-level grants" and "too coarse for regulated industries."
- [[2026-06-26-cortex-search-compression-strategies]] — the
CREATE CORTEX SEARCH SERVICEsurface is deliberately narrow:ON,ATTRIBUTES,WAREHOUSE,TARGET_LAG,EMBEDDING_MODEL. No compression, sharding, or partitioning clause exists. If you want partitioning, a separate service object is the only lever. Also records multi-index and bring-your-own-vectors reaching general availability 2026-03-12. - [[study-cortex-ai]] — billing has three moving parts (embedding tokens, warehouse credits for refresh, serving credits) and refresh is incremental only when a primary key is defined; without one, every refresh is a full reindex.
- [[2026-04-28-snowflake-enterprise-knowledge-management]] also carries the Atlan finding that the dominant production failure is ungoverned data entering the pipeline, not retrieval choice. That failure mode is orthogonal to partitioning.
What the web says
- The service is the access-control unit, and it is the only one Snowflake enforces. Snowflake's overview doc states that querying requires "USAGE privileges on the service itself, as well as on the database and schema in which the service resides," and that services "perform searches with owner's rights" following "the same security model as other Snowflake objects that run with owner's rights" (Cortex Search overview, docs.snowflake.com, fetched 2026-08-15).
- Owner's rights means base-table row access policies do not fire per querying user. Snowflake's own access-controls guide confirms this and prescribes the workaround: index an entitlement value as an
ATTRIBUTEScolumn, have the application readCURRENT_ROLE()from the authenticated session, and pass an explicit filter into the search call from backend code "so it is not exposed to the visiting user" (Getting Started with Access Controls for RAGs (Cortex Search), Snowflake developer guide, fetched 2026-08-15). Third-party security analysis reaches the same conclusion from the outside: Cortex Search "runs with owners' rights, not callers'," which can let a user reach values they lack SELECT on (Cyera, "Unexpected behavior in Snowflake's Cortex AI", undated, secondary). - Throughput is capped per service, and the cap is low. Default limits are "20 QPS for a single search service or 140 QPS across all services" in an account, with HTTP 429 on exceed (Cortex Search overview, ibid.). Seven services saturate the account ceiling.
- Size ceiling is 400M rows. "The result of the materialized query in the search service must be less than 400M rows in size to maintain optimal serving performance" (ibid.). At a typical five-chunks-per-document ratio that is roughly 80M documents per service, well above Fortune-2000 corpora. This is not the forcing limit.
- Serving is billed per gigabyte of index, not per service, and it accrues at idle. "The compute cost for this component is incurred per GB per month (GB/mo) of uncompressed indexed data" (worked example: 6.3 credits per GB-month), and "you incur these costs while the service is available to respond to queries, even if no queries are served during a given period." Embedding is per token (worked example: 0.05 credits per 1M tokens) and incremental: "the embedding cost is only incurred for added or changed documents" (Understanding cost for Cortex Search Services, docs.snowflake.com, fetched 2026-08-15). No per-service minimum footprint is documented.
- Full rebuilds are triggered by schema and materialization changes, not by data volume. "Any change to the schema of the source query causes a full refresh of the service, including vector embeddings and indexes," and a
CREATE OR REPLACEon the source table "causes the service to fully refresh and embed all vectors again" (cost doc, ibid.). This is the mechanism that makes one mega-index fragile. - Auto-suspend is public preview, not general availability. Announced 2026-05-11, minimum
AUTO_SUSPENDof 1800 seconds, resume "typically taking up to a few minutes" on the first query (May 11, 2026 release note). The overview page still labels it "Preview Feature — Open" as of this fetch. - Nothing relevant surfaced dated after the parent brief. Searches of Snowflake release notes returned 2026-03-12 (multi-index and bring-your-own vectors, general availability) and 2026-05-11 (auto-suspend, public preview) as the most recent Cortex Search items. Both predate 2026-06-17. I did not scan the full release-note archive, so treat this as "no change found," not "no change occurred."
Convergences and contradictions
- Convergence, with the mechanism corrected. The parent brief's rule — put isolation in the data layer, never the agent layer — is right, and in Cortex Search it argues for service partitioning rather than for a filter column. The
ATTRIBUTESfilter value is supplied by the caller. When the caller is a trusted Streamlit backend readingCURRENT_ROLE(), that is a real control. When the caller is an agent whose tool arguments a model composes, the filter has moved into exactly the layer the parent brief said must never hold the boundary. The parent brief's immutable-session-attribute plus row-access-policy pattern is a Cortex Agents and Cortex Analyst mechanism; owner's-rights execution means it does not reach the Search index the same way. - Contradiction with the vault's own prior claim, in degree rather than direction. [[2026-04-28-snowflake-enterprise-knowledge-management]] recommended service-per-business-unit as a flat rule. The documentation supports the recommendation but not the reasoning implied. It works because grant, refresh, and throughput are all per-service objects. It does not work because Cortex Search offers chunk-level role-aware retrieval, which it does not. That brief's own throwaway line — default RBAC is "service-level grants," too coarse for regulated industries — is actually the strongest argument for partitioning, because coarse-but-enforced beats fine-but-application-supplied.
- Tension on cost that cuts against the intuitive read. The intuition that N services cost roughly N× is wrong under pure partitioning and right under duplication. Serving is priced per gigabyte of indexed data, so splitting one 300 GB corpus into eight business-unit services is still about 300 GB. What multiplies is the number of refresh orchestrations, the operational surface, and — the real tax — any document that belongs to k business units and therefore gets embedded and indexed k times.
Synthesis for RDCO
The honest answer is yes, but for three reasons that are not the reason people say, and with one condition that most implementations will fail. Service partitioning contains three blast radii cleanly and provably. First, availability: a schema change to one business unit's source query forces a full re-embed and index rebuild of whatever service it belongs to. In a mega-index that means one team's pipeline edit re-embeds the entire corporate corpus and leaves every other business unit stale or degraded for the duration. Partitioned, it is one business unit's problem. Second, throughput: 20 queries per second is a per-service ceiling, and one enthusiastic business unit rolling out a chat surface will 429 everyone else off a shared index. Partitioned, each unit gets its own bucket, up to the account ceiling of 140. Third, offboarding and provability: dropping a service physically removes an index, which is a cleaner audit story than proving a filter predicate was always correctly applied.
The condition is that the grant graph has to partition too, and this is where the pattern usually collapses. Because Cortex Search runs with owner's rights and the enforced boundary is USAGE on the service object, partitioning contains leakage only if the callers are also partitioned. The moment a single company-wide assistant holds USAGE on all eight business-unit services, that agent is the union of all eight and the partitioning buys nothing on leakage. It still buys the availability and throughput containment above, which is not nothing, but the security argument evaporates. So the design rule is: partition services along entitlement boundaries and give each partition its own service role and its own calling application or agent. Do not partition along the org chart and then hand one super-agent every grant. That is theater, and an auditor who understands owner's rights will say so.
What partitioning does not contain, stated plainly. It does not contain bad-document poisoning within a unit — a poisoned document inside a business unit still poisons every answer that unit's users get, and if the document is shared across units it is duplicated into each service and poisons all of them. It does not contain the failure mode the vault already flagged as dominant, which is ungoverned data entering the pipeline upstream of retrieval. It does not help when the question is genuinely cross-unit: a partitioned estate turns a single ranked retrieval into a fan-out across N services plus a client-side merge, and you lose the single global reranker frame that made the scores comparable in the first place. That last item is the real cost of partitioning and it is a retrieval-quality regression, not an ops inconvenience. Cross-unit relevance dilution is a genuine argument for partitioning, but it is a quality argument wearing a security costume; it should be argued on its own merits.
The threshold, since the answer is conditional. Partition when any one of these holds: distinct entitlement populations with distinct calling applications; aggregate query load approaching 20 queries per second on a shared index; materially different refresh cadences or different rates of source-schema churn between units; or one unit carrying a sensitivity tier (protected health information, nonpublic personal information, licensed third-party feeds under redistribution terms) that the others do not. Keep one index when a single assistant serves everyone, load is comfortably under 20 queries per second, and cross-unit questions are common — in that shape you pay N× operational overhead for zero enforced isolation. On count, stay in single digits: seven services exhaust the account-wide 140 queries-per-second pool as a shared resource, and every service is another refresh orchestration, another target-lag policy, and another object in the fan-out. Service-per-team at forty teams is the failure mode on the other side. And check document overlap before committing: if more than roughly a quarter of the corpus is shared across units, the duplicate embedding and per-gigabyte serving tax plus fan-out complexity starts to favor one index with a genuinely trusted, non-agent application layer supplying the filter.
Why this is in the vault
It resolves an open follow-up from [[2026-06-17-multi-tenant-governance-shared-vector-store]] that gates the retrieval-layer design of the client-intelligence platform, and it corrects [[2026-04-28-snowflake-enterprise-knowledge-management]], which has been circulating an unqualified "service per business unit" recommendation into phData advisory framing without the owner's-rights caveat that determines whether the pattern actually contains anything.
Open follow-ups
- Does the Cortex Agents immutable-session-attribute mechanism do anything for the Search tool specifically, or does owner's-rights execution mean tenant attributes only constrain the Analyst / SQL tools in a mixed agent? Not verified here, and it changes the design if the answer is the former.
- Is there an undocumented per-service minimum serving footprint? The cost doc prices serving purely per gigabyte with no floor stated, which implies partitioning is cost-neutral. Worth an empirical test on a small account before quoting cost-neutrality to a client.
- What is the measured retrieval-quality cost of fan-out-plus-merge across N services versus a single global reranker on the same corpus? The partitioning recommendation currently has no number attached to its main downside.
- Is there a documented maximum number of
ATTRIBUTESfilter columns per service, and is the 140 queries-per-second account cap raisable via Snowflake support? Both bound the partitioning design and neither appeared in the docs fetched. - Auto-suspend is public preview as of 2026-08-15 with a 30-minute minimum and multi-minute resume. When it reaches general availability, does the resume latency make per-business-unit services viable for low-traffic units, or does the cold-start penalty push toward consolidation for the long tail?
- What does a defensible audit artifact look like for a partitioned estate — is
SNOWFLAKE.ACCOUNT_USAGEsufficient to prove "who could have seen what" per service, or does it still require the custom(query, retrieved_chunk_ids, answer, calling_role, timestamp)table the 2026-04-28 brief called for?
Related
- [[2026-06-17-multi-tenant-governance-shared-vector-store]] — the parent brief; supplies the flat-internal / hard-wall-external tenancy lock this question sits inside, and the isolation principle this brief re-mechanises.
- [[2026-04-28-snowflake-enterprise-knowledge-management]] — source of the unqualified service-per-business-unit claim this brief grounds and conditions.
- [[2026-06-26-cortex-search-compression-strategies]] — establishes that the Cortex Search DDL exposes no partitioning or sharding knob, so a separate service object is the only partitioning lever.
- [[study-cortex-ai]] — the
CREATE CORTEX SEARCH SERVICEsurface, embedding-model table, refresh semantics, and the three-component billing model. - [[2026-07-14-technically-turbopuffer-search-tooling]] — object-storage-backed search economics underlying Cortex Search's per-gigabyte serving price.
- [[2026-07-30-caf-fabric-neptune-vs-snowflake-native-backend]] — adjacent decision on the Snowflake-native Cortex Search spine for the same platform.
Sources
Vault:
- [[2026-06-17-multi-tenant-governance-shared-vector-store]] — rdco-vault/06-reference/research/2026-06-17-multi-tenant-governance-shared-vector-store.md
- [[2026-04-28-snowflake-enterprise-knowledge-management]] — rdco-vault/06-reference/research/2026-04-28-snowflake-enterprise-knowledge-management.md
- [[2026-06-26-cortex-search-compression-strategies]] — rdco-vault/06-reference/research/2026-06-26-cortex-search-compression-strategies.md
- [[study-cortex-ai]] — rdco-vault/01-projects/certifications/snowpro-genai-c02/study-cortex-ai.md
- [[2026-07-14-technically-turbopuffer-search-tooling]] — rdco-vault/06-reference/2026-07-14-technically-turbopuffer-search-tooling.md
- [[2026-07-30-caf-fabric-neptune-vs-snowflake-native-backend]] — rdco-vault/06-reference/research/2026-07-30-caf-fabric-neptune-vs-snowflake-native-backend.md
Web (primary — fetched and read 2026-08-15):
- Cortex Search overview — Snowflake docs — 400M-row ceiling, 20/140 queries-per-second limits, USAGE-on-service privilege model, owner's-rights execution, auto-suspend preview label.
- Understanding cost for Cortex Search Services — Snowflake docs — per-gigabyte-month serving price, idle accrual, incremental embedding, full-refresh triggers.
- Getting Started with Access Controls for RAGs (Cortex Search) — Snowflake developer guide — the official ATTRIBUTES-filter pattern, application-side filter derivation, owner's-rights confirmation.
Web (secondary — via search result summaries, not independently fetched):
- May 11, 2026: Auto-suspend and resume for Cortex Search Services (Public Preview) — Snowflake docs — 1800-second minimum, multi-minute resume.
- Unexpected behavior in Snowflake's Cortex AI — Cyera — independent confirmation of owner's-rights row-level-security bypass. Undated; treated as corroboration only.