Composite Policy: Limitations and Patterns
Composite policies let you group multiple policies into a single reusable unit
that you can apply across routes. While they simplify configuration and keep
your policies.json organized, there are important limitations to understand —
especially around nesting composite policies inside other composite policies.
This guide covers those limitations, explains the error messages you might encounter, and provides recommended patterns for scaling policy management.
How composite policies work
A composite policy references other policies by their name as defined in your
policies.json file. When a route uses a composite policy, Zuplo executes each
referenced policy in order, just as if you had listed them individually on the
route.
Code
In this example, any route that references security-group runs the
api-key-auth, rate-limit, and request-validation policies in sequence.
For full configuration details, see the Composite Inbound Policy and Composite Outbound Policy reference pages.
Limitations
Nested composite policies are not supported
You cannot place a composite policy inside another composite policy. While
Zuplo's configuration does not prevent you from referencing one composite policy
in another composite policy's policies array, doing so leads to unexpected
behavior at runtime.
Nested composite policies are not supported. Always list all required policies directly in a single, flat composite policy. Nesting composites inside other composites can cause policies to malfunction or produce confusing errors.
For example, the following configuration does not work as expected:
❌ Unsupported: nested composites
In this example, project-template references shared-template, which is
itself a composite policy. This nesting causes the inner policies to not execute
correctly.
Request validation inside nested composites
One specific failure mode involves the Request Validation policy. When used inside a nested composite policy, the Request Validation policy may not be able to resolve the OpenAPI schema for the current route. You may see an error similar to:
Code
This error does not mean your schema is missing from your OpenAPI specification. It indicates that the validation policy lost access to the route's schema context because of the unsupported nesting.
Circular references
Composite policies that reference each other (directly or indirectly) create circular references that can cause your gateway to fail. Always verify that your composite policy chains do not form loops.
Recommended patterns for policy reuse
Use flat composite policies
Instead of nesting composite policies, list every policy directly in a single composite:
✅ Flat composite with all policies listed
This approach is explicit and avoids any nesting issues. The trade-off is that when a "shared" set of policies changes, you need to update every composite policy that includes them.
Create purpose-specific composite policies
Group policies by function or security level. Rather than one universal composite, define composites that map to specific route requirements:
policies.json
Routes can then reference the appropriate composite by name without needing to repeat individual policy lists.
Use custom policies for advanced composition
When you need conditional logic or dynamic policy invocation, write a
custom code inbound policy that calls
context.invokeInboundPolicy() programmatically:
modules/conditional-policies.ts
This approach gives you full control over execution order and conditional logic. See Conditional Policy Execution for more examples.
Use context.invokeInboundPolicy() when you need to programmatically decide
which policies to run. Use composite policies when you have a fixed set of
policies that always run together.
Error messages and troubleshooting
"No schema defined for method..."
Cause: The Request Validation policy cannot find the OpenAPI schema for the current route. This commonly occurs when the validation policy runs inside a nested composite policy.
Fix: Move the Request Validation policy out of any nested composite structure. List it directly in a flat composite policy or directly on the route.
Gateway may fail due to circular references
Cause: Circular references in composite policy configuration. For example, policy A references policy B, and policy B references policy A.
Fix: Review your policies.json and verify that no composite policy
references another composite that eventually references it back. Trace the full
chain of policy references to identify the loop.
Policies execute in unexpected order
Cause: Policies within a composite run in the order listed in the policies
array. If you have multiple composites on a route, each composite runs its
policies sequentially, and the composites themselves run in the order they
appear on the route.
Fix: Verify the order of policies in your composite's policies array and
the order of policies assigned to your route.
Summary
- Composite policies group multiple policies into a single reusable reference.
- Nested composite policies are not supported. Always use flat composites that list all required policies directly.
- The Request Validation policy produces a "No schema defined" error when used inside nested composites.
- For advanced composition logic, use
context.invokeInboundPolicy()in a custom code policy. - Avoid circular references between composite policies.