Hello everyone! :wave: Apologies for bringing thi...
# opal
a
Hello everyone! πŸ‘‹ Apologies for bringing this up again β€” I'd really appreciate hearing from anyone who has experience running 500+ rego policies managed with the opal-server + opal-client stack. The problem: I run opa and opal-client-standalone as sidecars in the same k8s pod. During cold start, the initial policy sync takes over 10 minutes, during which the OPAL client reports an unhealthy status β€” causing the pod to fail both readiness and liveness probes. Opal-client logs:
Copy code
2026-03-03T20:36:11.372421+0000 | 16 | opal_client.policy_store.opa_client     | WARNING | OPA client health: False (policy: False, data: True)
2026-03-03T20:36:11.373165+0000 | 16 | uvicorn.protocols.http.httptools_impl   | INFO    | 10.100.35.127:51372 - "GET /healthcheck HTTP/1.1" 503
2026-03-03T20:36:11.379258+0000 | 16 | uvicorn.protocols.http.httptools_impl   | INFO    | 10.100.35.127:51384 - "GET /ready HTTP/1.1" 503
Root cause: OPAL pushes each policy individually via PUT /v1/policies/{path} to the OPA agent. With 500+ policies, each PUT takes ~0.5s+, and this duration appears to grow as more policies are loaded (likely because OPA recompiles/re-evaluates the entire policy set on every single insertion (not sure tho)). This sequential loading leads to a prohibitive startup time. OPA logs:
Copy code
{"client_addr":"[::1]:37922","level":"info","msg":"Received request.","req_body":"<policy_content>","req_id":3841,"req_method":"PUT","req_params":{},"req_path":"/v1/policies/main/domain/subdomain/policy1.rego","time":"2026-03-03T20:23:39Z"}
{"client_addr":"[::1]:37922","level":"info","msg":"Sent response.","req_id":3841,"req_method":"PUT","req_path":"/v1/policies/main/domain/subdomain/policy1.rego","resp_body":"{}\n","resp_bytes":3,"resp_duration":631.523340,"resp_status":200,"time":"2026-03-03T20:23:39Z"}
{"client_addr":"[::1]:37934","level":"info","msg":"Received request.","req_body":"<policy_content>","req_id":3842,"req_method":"PUT","req_params":{},"req_path":"/v1/policies/main/domain/subdomain/policy2.rego","time":"2026-03-03T20:23:39Z"}
{"client_addr":"[::1]:37934","level":"info","msg":"Sent response.","req_id":3842,"req_method":"PUT","req_path":"/v1/policies/main/domain/subdomain/policy2.rego","resp_body":"{}\n","resp_bytes":3,"resp_duration":716.441353,"resp_status":200,"time":"2026-03-03T20:23:39Z"}
What I've considered to solve: one idea is to use bundles and pre-bake the policies into the OPA container image (e.g. via opa run --bundle /policies, or different methods), so that OPA boots up instantly with all policies already compiled. However, OPAL client has no concept of a "starting commit hash" or awareness that OPA already has the policies β€” its internal state is in-memory and lost on every restart. So it would still perform the full sync via individual PUTs on every cold start, making the pre-bake effectively useless unless there's a way to tell OPAL "the store is already up-to-date as of commit X β€” only sync the delta." I’d be very interested to know: - whether others have seen similar behavior at this scale and how you handled/mitigated this - whether there is a way to make OPAL skip the initial full sync if OPA is already pre-loaded (e.g. by providing the last policy commit hash present in the bundle) - whether there is a way to switch OPAL to deliver policies as an OPA bundle instead of individual PUT calls Any real-world experience or recommendations would be very helpful. Thanks!!! πŸ™β˜ΊοΈ
a
Hi @Andrea Di Saverio, I'm an AI assistant for Permit.io. I'll analyze available sources and get back to you shortly.
This is a great question about scaling OPAL with a large number of policies. Based on the available documentation, here's what I can share: ​*Using API Bundle Server as Policy Source*​ OPAL does support fetching policies as bundles rather than from Git. You can configure the OPAL server to use an API bundle server as the policy source by setting: (1) β€’
OPAL_POLICY_SOURCE_TYPE=API
β€” Set your policy source type to
API
instead of
GIT
β€’
OPAL_POLICY_BUNDLE_URL
β€” Set your API bundle URL With this approach, the OPAL server fetches a
bundle.tar.gz
file from your bundle server, extracts it, and syncs it to clients. (2) The OPAL server will: β€’ Send a request to get the
bundle.tar.gz
file β€’ Extract it to the configured local path β€’ Make a git repo from its content to track changes β€’ Upon detecting a new bundle file (tracked by ETag or hashing) , request and save the new bundle ​*Bundle Server Authentication Options*​ You can configure authentication with your bundle server: , (1) β€’
OPAL_POLICY_BUNDLE_SERVER_TYPE
β€” Options:
HTTP
(authenticated with bearer token) or
AWS-S3
(authenticated with AWS REST Auth) β€’
OPAL_POLICY_BUNDLE_SERVER_TOKEN_ID
and
OPAL_POLICY_BUNDLE_SERVER_TOKEN
for credentials ​*Regarding Your Specific Questions*​ Unfortunately, the available documentation doesn't cover: β€’ A mechanism to tell OPAL "the store is already up-to-date as of commit X" β€’ Whether switching to bundle-based policy source changes how OPAL pushes policies to OPA (individual PUTs vs. bundle delivery) β€’ Specific guidance for 500+ policy deployments ​*Recommendation*​ For this advanced use case, I'd suggest reaching out to the community for real-world experience. You can also reach out over Email for more specialized guidance. Check out these potentially useful sources: β€’ Policy syncing from API β€’ OPAL Configuration Guide β€’ OPAL Client Would you like me to try to provide a general answer based on broader knowledge of OPA/OPAL patterns?
To learn more, see the sources I considered: [[1] OPAL Configuration Guide | OPAL](https://docs.opal.ac/getting-started/configuration) [[2] Policy syncing from API](https://docs.opal.ac/tutorials/track_an_api_bundle_server)
d
Hey @Andrea Di Saverio, did the Bot provide you with what you needed? Have you tried Bundling techniques like it suggests?
a
hi @david, thanks for your reply. The suggestion provided by the Bot is about using the bundle mechanism. I tried it, but it doesn't solve the problem since the bundle is only used by the opal-server to retrieve all the policies (bundled), but it doesn't affect the way the opal-client feeds the opa agent: it still does the sequence of POST calls to the agent, so the problem is not solved.
d
Understood, I will confer with the team and get back to you πŸ™‚
a
thank you a lot β™₯️ very curious about real-world experiences from you
o
There's no alternative solution here. reduce the number of files you have, compile them together (as part of the bundle server for example).