Rate limiting issues with multiple policies in a key

I am using Open Source Tyk
I have encountered 1 issue while using multiple policies
Let me explain

I have 2 policies in policies/policies.json
In each policy i have different endpoints configured with rate limit

When i am creating a key, by passing both policies in body
I get a key, through which both apis in respected policy can be accessed… No issues here
But when i am testing rate limit for both policies one single rate limit is applied on both api endpoints (both api has different rate limiting params in policy)

Here are some of my json

Policies.json

{

  "Policy1": {

    "access_rights": {

      "cf841dff-ba1a-4ee9-a497-25c83c8f8c88": {

        "allowed_urls": [],

        "api_id": "cf841dff-ba1a-4ee9-a497-25c83c8f8c88",

        "api_name": "authapi6",

        "versions": [

            "Default"

        ]

      }

    },

    "active": true,

    "name": "Policy 1",

    "rate": 5,

    "per": 10,

    "quota_max": -1,

    "quota_renewal_rate": 3600,

    "state": "active",

    "tags": ["Startup Users"]

  },

  "Policy2": {

    "access_rights": {

      "62156f9b-f086-4dda-99b6-f2d63d9de951": {

        "allowed_urls": [],

        "api_id": "62156f9b-f086-4dda-99b6-f2d63d9de951",

        "api_name": "authapi7",

        "versions": [

            "Default"

        ]

      }

    },

    "active": true,

    "name": "Policy 2",

    "rate": 10,

    "per": 15,

    "quota_max": -1,

    "quota_renewal_rate": 3600,

    "state": "active",

    "tags": ["Startup Users"]

  }

}

Key object when I do GET key in postman

{
    "last_check": 0,
    "allowance": 0,
    "rate": 20,
    "per": 50,
    "throttle_interval": 0,
    "throttle_retry_limit": 0,
    "max_query_depth": 0,
    "date_created": "2022-02-09T10:42:38.0918179Z",
    "expires": 0,
    "quota_max": -1,
    "quota_renews": 1644406958,
    "quota_remaining": -1,
    "quota_renewal_rate": 3600,
    "access_rights": {
        "62156f9b-f086-4dda-99b6-f2d63d9de951": {
            "api_name": "authapi7",
            "api_id": "62156f9b-f086-4dda-99b6-f2d63d9de951",
            "versions": [
                "Default"
            ],
            "allowed_urls": [],
            "restricted_types": null,
            "limit": {
                "rate": 10,
                "per": 15,
                "throttle_interval": 0,
                "throttle_retry_limit": 0,
                "max_query_depth": 0,
                "quota_max": -1,
                "quota_renews": 0,
                "quota_remaining": 0,
                "quota_renewal_rate": 3600
            },
            "field_access_rights": null,
            "allowance_scope": ""
        },
        "cf841dff-ba1a-4ee9-a497-25c83c8f8c88": {
            "api_name": "authapi6",
            "api_id": "cf841dff-ba1a-4ee9-a497-25c83c8f8c88",
            "versions": [
                "Default"
            ],
            "allowed_urls": [],
            "restricted_types": null,
            "limit": {
                "rate": 5,
                "per": 10,
                "throttle_interval": 0,
                "throttle_retry_limit": 0,
                "max_query_depth": 0,
                "quota_max": -1,
                "quota_renews": 0,
                "quota_remaining": 0,
                "quota_renewal_rate": 3600
            },
            "field_access_rights": null,
            "allowance_scope": ""
        }
    },
    "org_id": "",
    "oauth_client_id": "",
    "oauth_keys": null,
    "certificate": "",
    "basic_auth_data": {
        "password": "",
        "hash_type": ""
    },
    "jwt_data": {
        "secret": ""
    },
    "hmac_enabled": false,
    "enable_http_signature_validation": false,
    "hmac_string": "",
    "rsa_certificate_id": "",
    "is_inactive": false,
    "apply_policy_id": "",
    "apply_policies": [
        "Policy1",
        "Policy2"
    ],
    "data_expires": 0,
    "monitor": {
        "trigger_limits": null
    },
    "enable_detail_recording": false,
    "enable_detailed_recording": false,
    "meta_data": {},
    "tags": [
        "Startup Users"
    ],
    "alias": "",
    "last_updated": "1644403358",
    "id_extractor_deadline": 0,
    "session_lifetime": 0
}

Hi @Shivam_Gupta, welcome to the community.

When using policies, the approach is a bit different. There is a partitions property in policies that allows you to specify whether the access control, rate limit and quotas are enforced or not. This can allow you to have similar/different rate limits/quotas for each api.

The trick is to set per_api value in the partitions property to true. This way each policy will handle it’s own set of security options on a per api basis just like you would have it in the Key Level security.

Snippet of the Partitions section

"partitions": {
			"acl": false,
			"complexity": false,
			"per_api": true,
			"quota": false,
			"rate_limit": false
		}

Full section of how policy would look like

"Policy3": {
		"access_rights": {
			"cf841dff-ba1a-4ee9-a497-25c83c8f8c88": {
				"allowed_urls": [],
				"api_id": "cf841dff-ba1a-4ee9-a497-25c83c8f8c88",
				"api_name": "authapi6",
				"versions": [
					"Default"
				],
				"allowed_urls": [],
				"restricted_types": null,
				"limit": {
					"rate": 5,
					"per": 10,
					"throttle_interval": 0,
					"throttle_retry_limit": 0,
					"max_query_depth": 0,
					"quota_max": 60,
					"quota_renews": 1644434574,
					"quota_remaining": 60,
					"quota_renewal_rate": 60
				},
				"field_access_rights": null,
				"allowance_scope": ""
			},
			"62156f9b-f086-4dda-99b6-f2d63d9de951": {
				"allowed_urls": [],
				"api_id": "62156f9b-f086-4dda-99b6-f2d63d9de951",
				"api_name": "authapi7",
				"versions": [
					"Default"
				],
				"allowed_urls": [],
				"restricted_types": null,
				"limit": {
					"rate": 10,
					"per": 15,
					"throttle_interval": 0,
					"throttle_retry_limit": 0,
					"max_query_depth": 0,
					"quota_max": 60,
					"quota_renews": 1644434574,
					"quota_remaining": 60,
					"quota_renewal_rate": 60
				},
				"field_access_rights": null,
				"allowance_scope": ""
			}
		},
		"active": true,
		"name": "Policy 3",
		"quota_max": -1,
		"quota_renewal_rate": 3600,
		"state": "active",
		"tags": [
			"Startup Users"
		],
		"partitions": {
			"acl": false,
			"complexity": false,
			"per_api": true,
			"quota": false,
			"rate_limit": false
		}
	}

Sadly I cannot find the a reference to per_api in our documentation however, you can visit partitioning policies to learn more about enforcing similar security options across apis/keys.

Hope this helps.

Hi @Olu , I am glad that response in Tyk community is so good.
But the solution you gave is for mutiple api in single policy right?

Use case over here is I have 2 policies & both policies have there own values for rate and per, and also both policy have single but different api in access_rights
And I want to generate a common key for both the policies
Expectation should be that when i apply the generated key in api of Policy1 then Policy1’s rate limit should get applied on it and if use same key in api of Policy2 then Policy2’s rate limit should get applied

So, i have mentioned both the policies in key’s payload and I get a key then that key gives access to both policy but doesn’t perform rate limit and quota as expected

JSON for Policies

{
  "Policy1": {
    "access_rights": {
      "e34967cf-743d-4646-a208-c102d35c548d": {
        "api_id": "e34967cf-743d-4646-a208-c102d35c548d",
        "api_name": "limitTest",
        "versions": [
            "default"
        ]
      }
    },
    "active": true,
    "name": "Policy 1",
    "org_id":"",
    "rate": 3,
    "per": 6,
    "quota_max": -1,
    "quota_renewal_rate": 3600,
    "state": "active",
    "tags": [],
    "partitions": {
      "acl": false,
      "complexity": false,
      "per_api": true,
      "quota": false,
      "rate_limit": false
      }
  },
  "Policy2": {
    "access_rights": {
      "7c729c71-c38e-4034-8564-527584d5c920": {
        "allowed_urls": [],
        "api_id": "7c729c71-c38e-4034-8564-527584d5c920",
        "api_name": "limitTest2",
        "versions": [
            "default"
        ]
      }
    },
    "active": true,
    "org_id":"",
    "name": "Policy 2",
    "rate": 5,
    "per": 10,
    "quota_max": -1,
    "quota_renewal_rate": 3600,
    "state": "active",
    "tags": [],
    "partitions": {
      "acl": false,
      "complexity": false,
      "per_api": true,
      "quota": false,
      "rate_limit": false
      }
  }

}

Payload of Key

{
    "apply_policies":["Policy1","Policy2"]
}

OR

{
    "apply_policies":["Policy1","Policy2"],
    "org_id":""
}
#(both give same results in all scenarios)

JSON data of Key when GET operation is performed

{
    "last_check": 0,
    "allowance": 0,
    "rate": 0,
    "per": 0,
    "throttle_interval": 0,
    "throttle_retry_limit": 0,
    "max_query_depth": 0,
    "date_created": "2022-02-23T14:17:57.221197Z",
    "expires": 0,
    "quota_max": 0,
    "quota_renews": 1645625877,
    "quota_remaining": 0,
    "quota_renewal_rate": 0,
    "access_rights": {
        "7c729c71-c38e-4034-8564-527584d5c920": {
            "api_name": "limitTest2",
            "api_id": "7c729c71-c38e-4034-8564-527584d5c920",
            "versions": [
                "default"
            ],
            "allowed_urls": [],
            "restricted_types": null,
            "limit": {
                "rate": 5,
                "per": 10,
                "throttle_interval": 0,
                "throttle_retry_limit": 0,
                "max_query_depth": 0,
                "quota_max": -1,
                "quota_renews": 0,
                "quota_remaining": 0,
                "quota_renewal_rate": 3600
            },
            "field_access_rights": null,
            "allowance_scope": ""
        },
        "e34967cf-743d-4646-a208-c102d35c548d": {
            "api_name": "limitTest",
            "api_id": "e34967cf-743d-4646-a208-c102d35c548d",
            "versions": [
                "default"
            ],
            "allowed_urls": null,
            "restricted_types": null,
            "limit": {
                "rate": 3,
                "per": 6,
                "throttle_interval": 0,
                "throttle_retry_limit": 0,
                "max_query_depth": 0,
                "quota_max": -1,
                "quota_renews": 0,
                "quota_remaining": 0,
                "quota_renewal_rate": 3600
            },
            "field_access_rights": null,
            "allowance_scope": ""
        }
    },
    "org_id": "",
    "oauth_client_id": "",
    "oauth_keys": null,
    "certificate": "",
    "basic_auth_data": {
        "password": "",
        "hash_type": ""
    },
    "jwt_data": {
        "secret": ""
    },
    "hmac_enabled": false,
    "enable_http_signature_validation": false,
    "hmac_string": "",
    "rsa_certificate_id": "",
    "is_inactive": false,
    "apply_policy_id": "",
    "apply_policies": [
        "Policy1",
        "Policy2"
    ],
    "data_expires": 0,
    "monitor": {
        "trigger_limits": null
    },
    "enable_detail_recording": false,
    "enable_detailed_recording": false,
    "meta_data": {},
    "tags": [],
    "alias": "",
    "last_updated": "1645625877",
    "id_extractor_deadline": 0,
    "session_lifetime": 0
}

# In one can notice that allowance_scope is empty, if we expect same behavior using multiple API's direct instead of Policies then allowance_scope is filled with respective ApiId  

If, in partition of Policy1 rate_limit is set to true(all other field in partition is false) and partition of Policy2 is set to false(all other field in partition is false) then API of Policy1 shows error access has been disallowed

JSON data of this key

{
    "last_check": 0,
    "allowance": 0,
    "rate": 5,
    "per": 10,
    "throttle_interval": 0,
    "throttle_retry_limit": 0,
    "max_query_depth": 0,
    "date_created": "2022-02-23T14:33:23.8047677Z",
    "expires": 0,
    "quota_max": -1,
    "quota_renews": 1645630403,
    "quota_remaining": 0,
    "quota_renewal_rate": 3600,
    "access_rights": {
        "7c729c71-c38e-4034-8564-527584d5c920": {
            "api_name": "limitTest2",
            "api_id": "7c729c71-c38e-4034-8564-527584d5c920",
            "versions": [
                "default"
            ],
            "allowed_urls": [],
            "restricted_types": null,
            "limit": {
                "rate": 5,
                "per": 10,
                "throttle_interval": 0,
                "throttle_retry_limit": 0,
                "max_query_depth": 0,
                "quota_max": -1,
                "quota_renews": 0,
                "quota_remaining": 0,
                "quota_renewal_rate": 3600
            },
            "field_access_rights": null,
            "allowance_scope": ""
        }
    },
    "org_id": "",
    "oauth_client_id": "",
    "oauth_keys": null,
    "certificate": "",
    "basic_auth_data": {
        "password": "",
        "hash_type": ""
    },
    "jwt_data": {
        "secret": ""
    },
    "hmac_enabled": false,
    "enable_http_signature_validation": false,
    "hmac_string": "",
    "rsa_certificate_id": "",
    "is_inactive": false,
    "apply_policy_id": "",
    "apply_policies": [
        "Policy1",
        "Policy2"
    ],
    "data_expires": 0,
    "monitor": {
        "trigger_limits": null
    },
    "enable_detail_recording": false,
    "enable_detailed_recording": false,
    "meta_data": {},
    "tags": [],
    "alias": "",
    "last_updated": "1645626803",
    "id_extractor_deadline": 0,
    "session_lifetime": 0
}

And in vice-versa condition Policy2’s API shows error “Acces had been disallowed”

Key JSON data for it

{
    "last_check": 0,
    "allowance": 0,
    "rate": 5,
    "per": 10,
    "throttle_interval": 0,
    "throttle_retry_limit": 0,
    "max_query_depth": 0,
    "date_created": "2022-02-23T14:35:05.3460764Z",
    "expires": 0,
    "quota_max": -1,
    "quota_renews": 1645630505,
    "quota_remaining": 0,
    "quota_renewal_rate": 3600,
    "access_rights": {
        "e34967cf-743d-4646-a208-c102d35c548d": {
            "api_name": "limitTest",
            "api_id": "e34967cf-743d-4646-a208-c102d35c548d",
            "versions": [
                "default"
            ],
            "allowed_urls": null,
            "restricted_types": null,
            "limit": {
                "rate": 3,
                "per": 6,
                "throttle_interval": 0,
                "throttle_retry_limit": 0,
                "max_query_depth": 0,
                "quota_max": -1,
                "quota_renews": 0,
                "quota_remaining": 0,
                "quota_renewal_rate": 3600
            },
            "field_access_rights": null,
            "allowance_scope": ""
        }
    },
    "org_id": "",
    "oauth_client_id": "",
    "oauth_keys": null,
    "certificate": "",
    "basic_auth_data": {
        "password": "",
        "hash_type": ""
    },
    "jwt_data": {
        "secret": ""
    },
    "hmac_enabled": false,
    "enable_http_signature_validation": false,
    "hmac_string": "",
    "rsa_certificate_id": "",
    "is_inactive": false,
    "apply_policy_id": "",
    "apply_policies": [
        "Policy1",
        "Policy2"
    ],
    "data_expires": 0,
    "monitor": {
        "trigger_limits": null
    },
    "enable_detail_recording": false,
    "enable_detailed_recording": false,
    "meta_data": {},
    "tags": [],
    "alias": "",
    "last_updated": "1645626905",
    "id_extractor_deadline": 0,
    "session_lifetime": 0
}

In short API in policy of one with rate_limit as true in partitions gives error

When rate_limit in both partitions are kept true then it doesn’t creates a key shows error

{
    "status": "error",
    "message": "Failed to create key, ensure security settings are correct."
}

Logs says:- “attempting to apply policy from different organisation to key, skipping”

Can anyone explain me this behavior, and give me solution for my use case

Hello @Shivam_Gupta

What you can do is create policies that have rate limits that are managed per API rather than globally. Let me share my example for you.

Here are my example API definitions:

Test API 1

{
    "api_id": "c82f9012376a43ee6ea88fca3107729b",
    "jwt_issued_at_validation_skew": 0,
    "upstream_certificates": {},
    "use_keyless": false,
    "enable_coprocess_auth": false,
    "base_identity_provided_by": "",
    "custom_middleware": {
      "pre": [],
      "post": [],
      "post_key_auth": [],
      "auth_check": {
        "name": "",
        "path": "",
        "require_session": false,
        "raw_body_only": false
      },
      "response": [],
      "driver": "",
      "id_extractor": {
        "extract_from": "",
        "extract_with": "",
        "extractor_config": {}
      }
    },
    "disable_quota": false,
    "custom_middleware_bundle": "",
    "cache_options": {
      "cache_timeout": 60,
      "enable_cache": true,
      "cache_all_safe_requests": false,
      "cache_response_codes": [],
      "enable_upstream_cache_control": false,
      "cache_control_ttl_header": "",
      "cache_by_headers": []
    },
    "enable_ip_blacklisting": false,
    "tag_headers": [],
    "jwt_scope_to_policy_mapping": {},
    "pinned_public_keys": {},
    "expire_analytics_after": 0,
    "domain": "",
    "openid_options": {
      "providers": [],
      "segregate_by_client": false
    },
    "jwt_policy_field_name": "",
    "enable_proxy_protocol": false,
    "jwt_default_policies": [],
    "active": true,
    "jwt_expires_at_validation_skew": 0,
    "config_data": {},
    "notifications": {
      "shared_secret": "",
      "oauth_on_keychange_url": ""
    },
    "jwt_client_base_field": "",
    "auth": {
      "use_param": false,
      "param_name": "",
      "use_cookie": false,
      "cookie_name": "",
      "auth_header_name": "Authorization",
      "use_certificate": false,
      "validate_signature": false,
      "signature": {
        "algorithm": "",
        "header": "",
        "secret": "",
        "allowed_clock_skew": 0,
        "error_code": 0,
        "error_message": ""
      }
    },
    "check_host_against_uptime_tests": false,
    "auth_provider": {
      "name": "",
      "storage_engine": "",
      "meta": {}
    },
    "blacklisted_ips": [],
    "graphql": {
      "schema": "",
      "enabled": false,
      "engine": {
        "field_configs": [],
        "data_sources": []
      },
      "type_field_configurations": [],
      "execution_mode": "proxyOnly",
      "proxy": {
        "auth_headers": {}
      },
      "subgraph": {
        "sdl": ""
      },
      "supergraph": {
        "subgraphs": [],
        "merged_sdl": "",
        "global_headers": {}
      },
      "version": "2",
      "playground": {
        "enabled": false,
        "path": ""
      }
    },
    "hmac_allowed_clock_skew": -1,
    "dont_set_quota_on_create": false,
    "uptime_tests": {
      "check_list": [],
      "config": {
        "expire_utime_after": 0,
        "service_discovery": {
          "use_discovery_service": false,
          "query_endpoint": "",
          "use_nested_query": false,
          "parent_data_path": "",
          "data_path": "",
          "cache_timeout": 60
        },
        "recheck_wait": 0
      }
    },
    "enable_jwt": false,
    "do_not_track": false,
    "name": "Test API 1",
    "slug": "test-api-1",
    "oauth_meta": {
      "allowed_access_types": [],
      "allowed_authorize_types": [],
      "auth_login_redirect": ""
    },
    "CORS": {
      "enable": false,
      "max_age": 24,
      "allow_credentials": false,
      "exposed_headers": [],
      "allowed_headers": [
        "Origin",
        "Accept",
        "Content-Type",
        "X-Requested-With",
        "Authorization"
      ],
      "options_passthrough": false,
      "debug": false,
      "allowed_origins": [
        "*"
      ],
      "allowed_methods": [
        "GET",
        "POST",
        "HEAD"
      ]
    },
    "event_handlers": {
      "events": {}
    },
    "proxy": {
      "target_url": "http://httpbin.org/",
      "service_discovery": {
        "endpoint_returns_list": false,
        "cache_timeout": 0,
        "parent_data_path": "",
        "query_endpoint": "",
        "use_discovery_service": false,
        "_sd_show_port_path": false,
        "target_path": "",
        "use_target_list": false,
        "use_nested_query": false,
        "data_path": "",
        "port_data_path": ""
      },
      "check_host_against_uptime_tests": false,
      "transport": {
        "ssl_insecure_skip_verify": false,
        "ssl_min_version": 0,
        "proxy_url": "",
        "ssl_ciphers": []
      },
      "target_list": [],
      "preserve_host_header": false,
      "strip_listen_path": true,
      "enable_load_balancing": false,
      "listen_path": "/test-api-1/",
      "disable_strip_slash": true
    },
    "client_certificates": [],
    "use_basic_auth": false,
    "version_data": {
      "not_versioned": true,
      "default_version": "",
      "versions": {
        "Default": {
          "name": "Default",
          "expires": "",
          "paths": {
            "ignored": [],
            "white_list": [],
            "black_list": []
          },
          "use_extended_paths": true,
          "extended_paths": {
            "ignored": [],
            "white_list": [],
            "black_list": [],
            "transform": [],
            "transform_response": [],
            "transform_jq": [],
            "transform_jq_response": [],
            "transform_headers": [],
            "transform_response_headers": [],
            "hard_timeouts": [],
            "circuit_breakers": [],
            "url_rewrites": [],
            "virtual": [],
            "size_limits": [],
            "method_transforms": [],
            "track_endpoints": [],
            "do_not_track_endpoints": [],
            "validate_json": [],
            "internal": []
          },
          "global_headers": {},
          "global_headers_remove": [],
          "global_response_headers": {},
          "global_response_headers_remove": [],
          "ignore_endpoint_case": false,
          "global_size_limit": 0,
          "override_target": ""
        }
      }
    },
    "jwt_scope_claim_name": "",
    "use_standard_auth": true,
    "session_lifetime": 0,
    "hmac_allowed_algorithms": [],
    "disable_rate_limit": false,
    "definition": {
      "location": "header",
      "key": "x-api-version",
      "strip_path": false
    },
    "use_oauth2": false,
    "jwt_source": "",
    "jwt_signing_method": "",
    "jwt_not_before_validation_skew": 0,
    "use_go_plugin_auth": false,
    "jwt_identity_base_field": "",
    "allowed_ips": [],
    "request_signing": {
      "is_enabled": false,
      "secret": "",
      "key_id": "",
      "algorithm": "",
      "header_list": [],
      "certificate_id": "",
      "signature_header": ""
    },
    "org_id": "5e9d9544a1dcd60001d0ed20",
    "enable_ip_whitelisting": false,
    "global_rate_limit": {
      "rate": 0,
      "per": 0
    },
    "protocol": "",
    "enable_context_vars": false,
    "tags": [],
    "basic_auth": {
      "disable_caching": false,
      "cache_ttl": 0,
      "extract_from_body": false,
      "body_user_regexp": "",
      "body_password_regexp": ""
    },
    "listen_port": 0,
    "session_provider": {
      "name": "",
      "storage_engine": "",
      "meta": {}
    },
    "auth_configs": {
      "authToken": {
        "use_param": false,
        "param_name": "",
        "use_cookie": false,
        "cookie_name": "",
        "auth_header_name": "Authorization",
        "use_certificate": false,
        "validate_signature": false,
        "signature": {
          "algorithm": "",
          "header": "",
          "secret": "",
          "allowed_clock_skew": 0,
          "error_code": 0,
          "error_message": ""
        }
      },
      "basic": {
        "use_param": false,
        "param_name": "",
        "use_cookie": false,
        "cookie_name": "",
        "auth_header_name": "Authorization",
        "use_certificate": false,
        "validate_signature": false,
        "signature": {
          "algorithm": "",
          "header": "",
          "secret": "",
          "allowed_clock_skew": 0,
          "error_code": 0,
          "error_message": ""
        }
      },
      "coprocess": {
        "use_param": false,
        "param_name": "",
        "use_cookie": false,
        "cookie_name": "",
        "auth_header_name": "Authorization",
        "use_certificate": false,
        "validate_signature": false,
        "signature": {
          "algorithm": "",
          "header": "",
          "secret": "",
          "allowed_clock_skew": 0,
          "error_code": 0,
          "error_message": ""
        }
      },
      "hmac": {
        "use_param": false,
        "param_name": "",
        "use_cookie": false,
        "cookie_name": "",
        "auth_header_name": "Authorization",
        "use_certificate": false,
        "validate_signature": false,
        "signature": {
          "algorithm": "",
          "header": "",
          "secret": "",
          "allowed_clock_skew": 0,
          "error_code": 0,
          "error_message": ""
        }
      },
      "jwt": {
        "use_param": false,
        "param_name": "",
        "use_cookie": false,
        "cookie_name": "",
        "auth_header_name": "Authorization",
        "use_certificate": false,
        "validate_signature": false,
        "signature": {
          "algorithm": "",
          "header": "",
          "secret": "",
          "allowed_clock_skew": 0,
          "error_code": 0,
          "error_message": ""
        }
      },
      "oauth": {
        "use_param": false,
        "param_name": "",
        "use_cookie": false,
        "cookie_name": "",
        "auth_header_name": "Authorization",
        "use_certificate": false,
        "validate_signature": false,
        "signature": {
          "algorithm": "",
          "header": "",
          "secret": "",
          "allowed_clock_skew": 0,
          "error_code": 0,
          "error_message": ""
        }
      },
      "oidc": {
        "use_param": false,
        "param_name": "",
        "use_cookie": false,
        "cookie_name": "",
        "auth_header_name": "Authorization",
        "use_certificate": false,
        "validate_signature": false,
        "signature": {
          "algorithm": "",
          "header": "",
          "secret": "",
          "allowed_clock_skew": 0,
          "error_code": 0,
          "error_message": ""
        }
      }
    },
    "strip_auth_data": false,
    "id": "6219065395210c0001771abd",
    "certificates": [],
    "enable_signature_checking": false,
    "use_openid": false,
    "internal": false,
    "jwt_skip_kid": false,
    "enable_batch_request_support": false,
    "enable_detailed_recording": false,
    "response_processors": [],
    "use_mutual_tls_auth": false
  }

Test API 2

{
    "api_id": "3f484ed934f24bb548b57a93e00b2262",
    "jwt_issued_at_validation_skew": 0,
    "upstream_certificates": {},
    "use_keyless": false,
    "enable_coprocess_auth": false,
    "base_identity_provided_by": "",
    "custom_middleware": {
      "pre": [],
      "post": [],
      "post_key_auth": [],
      "auth_check": {
        "name": "",
        "path": "",
        "require_session": false,
        "raw_body_only": false
      },
      "response": [],
      "driver": "",
      "id_extractor": {
        "extract_from": "",
        "extract_with": "",
        "extractor_config": {}
      }
    },
    "disable_quota": false,
    "custom_middleware_bundle": "",
    "cache_options": {
      "cache_timeout": 60,
      "enable_cache": true,
      "cache_all_safe_requests": false,
      "cache_response_codes": [],
      "enable_upstream_cache_control": false,
      "cache_control_ttl_header": "",
      "cache_by_headers": []
    },
    "enable_ip_blacklisting": false,
    "tag_headers": [],
    "jwt_scope_to_policy_mapping": {},
    "pinned_public_keys": {},
    "expire_analytics_after": 0,
    "domain": "",
    "openid_options": {
      "providers": [],
      "segregate_by_client": false
    },
    "jwt_policy_field_name": "",
    "enable_proxy_protocol": false,
    "jwt_default_policies": [],
    "active": true,
    "jwt_expires_at_validation_skew": 0,
    "config_data": {},
    "notifications": {
      "shared_secret": "",
      "oauth_on_keychange_url": ""
    },
    "jwt_client_base_field": "",
    "auth": {
      "use_param": false,
      "param_name": "",
      "use_cookie": false,
      "cookie_name": "",
      "auth_header_name": "Authorization",
      "use_certificate": false,
      "validate_signature": false,
      "signature": {
        "algorithm": "",
        "header": "",
        "secret": "",
        "allowed_clock_skew": 0,
        "error_code": 0,
        "error_message": ""
      }
    },
    "check_host_against_uptime_tests": false,
    "auth_provider": {
      "name": "",
      "storage_engine": "",
      "meta": {}
    },
    "blacklisted_ips": [],
    "graphql": {
      "schema": "",
      "enabled": false,
      "engine": {
        "field_configs": [],
        "data_sources": []
      },
      "type_field_configurations": [],
      "execution_mode": "proxyOnly",
      "proxy": {
        "auth_headers": {}
      },
      "subgraph": {
        "sdl": ""
      },
      "supergraph": {
        "subgraphs": [],
        "merged_sdl": "",
        "global_headers": {}
      },
      "version": "2",
      "playground": {
        "enabled": false,
        "path": ""
      }
    },
    "hmac_allowed_clock_skew": -1,
    "dont_set_quota_on_create": false,
    "uptime_tests": {
      "check_list": [],
      "config": {
        "expire_utime_after": 0,
        "service_discovery": {
          "use_discovery_service": false,
          "query_endpoint": "",
          "use_nested_query": false,
          "parent_data_path": "",
          "data_path": "",
          "cache_timeout": 60
        },
        "recheck_wait": 0
      }
    },
    "enable_jwt": false,
    "do_not_track": false,
    "name": "Test API 2",
    "slug": "test-api-2",
    "oauth_meta": {
      "allowed_access_types": [],
      "allowed_authorize_types": [],
      "auth_login_redirect": ""
    },
    "CORS": {
      "enable": false,
      "max_age": 24,
      "allow_credentials": false,
      "exposed_headers": [],
      "allowed_headers": [
        "Origin",
        "Accept",
        "Content-Type",
        "X-Requested-With",
        "Authorization"
      ],
      "options_passthrough": false,
      "debug": false,
      "allowed_origins": [
        "*"
      ],
      "allowed_methods": [
        "GET",
        "POST",
        "HEAD"
      ]
    },
    "event_handlers": {
      "events": {}
    },
    "proxy": {
      "target_url": "http://httpbin.org/",
      "service_discovery": {
        "endpoint_returns_list": false,
        "cache_timeout": 0,
        "parent_data_path": "",
        "query_endpoint": "",
        "use_discovery_service": false,
        "_sd_show_port_path": false,
        "target_path": "",
        "use_target_list": false,
        "use_nested_query": false,
        "data_path": "",
        "port_data_path": ""
      },
      "check_host_against_uptime_tests": false,
      "transport": {
        "ssl_insecure_skip_verify": false,
        "ssl_min_version": 0,
        "proxy_url": "",
        "ssl_ciphers": []
      },
      "target_list": [],
      "preserve_host_header": false,
      "strip_listen_path": true,
      "enable_load_balancing": false,
      "listen_path": "/test-api-2/",
      "disable_strip_slash": true
    },
    "client_certificates": [],
    "use_basic_auth": false,
    "version_data": {
      "not_versioned": true,
      "default_version": "",
      "versions": {
        "Default": {
          "name": "Default",
          "expires": "",
          "paths": {
            "ignored": [],
            "white_list": [],
            "black_list": []
          },
          "use_extended_paths": true,
          "extended_paths": {
            "ignored": [],
            "white_list": [],
            "black_list": [],
            "transform": [],
            "transform_response": [],
            "transform_jq": [],
            "transform_jq_response": [],
            "transform_headers": [],
            "transform_response_headers": [],
            "hard_timeouts": [],
            "circuit_breakers": [],
            "url_rewrites": [],
            "virtual": [],
            "size_limits": [],
            "method_transforms": [],
            "track_endpoints": [],
            "do_not_track_endpoints": [],
            "validate_json": [],
            "internal": []
          },
          "global_headers": {},
          "global_headers_remove": [],
          "global_response_headers": {},
          "global_response_headers_remove": [],
          "ignore_endpoint_case": false,
          "global_size_limit": 0,
          "override_target": ""
        }
      }
    },
    "jwt_scope_claim_name": "",
    "use_standard_auth": true,
    "session_lifetime": 0,
    "hmac_allowed_algorithms": [],
    "disable_rate_limit": false,
    "definition": {
      "location": "header",
      "key": "x-api-version",
      "strip_path": false
    },
    "use_oauth2": false,
    "jwt_source": "",
    "jwt_signing_method": "",
    "jwt_not_before_validation_skew": 0,
    "use_go_plugin_auth": false,
    "jwt_identity_base_field": "",
    "allowed_ips": [],
    "request_signing": {
      "is_enabled": false,
      "secret": "",
      "key_id": "",
      "algorithm": "",
      "header_list": [],
      "certificate_id": "",
      "signature_header": ""
    },
    "org_id": "5e9d9544a1dcd60001d0ed20",
    "enable_ip_whitelisting": false,
    "global_rate_limit": {
      "rate": 0,
      "per": 0
    },
    "protocol": "",
    "enable_context_vars": false,
    "tags": [],
    "basic_auth": {
      "disable_caching": false,
      "cache_ttl": 0,
      "extract_from_body": false,
      "body_user_regexp": "",
      "body_password_regexp": ""
    },
    "listen_port": 0,
    "session_provider": {
      "name": "",
      "storage_engine": "",
      "meta": {}
    },
    "auth_configs": {
      "authToken": {
        "use_param": false,
        "param_name": "",
        "use_cookie": false,
        "cookie_name": "",
        "auth_header_name": "Authorization",
        "use_certificate": false,
        "validate_signature": false,
        "signature": {
          "algorithm": "",
          "header": "",
          "secret": "",
          "allowed_clock_skew": 0,
          "error_code": 0,
          "error_message": ""
        }
      },
      "basic": {
        "use_param": false,
        "param_name": "",
        "use_cookie": false,
        "cookie_name": "",
        "auth_header_name": "Authorization",
        "use_certificate": false,
        "validate_signature": false,
        "signature": {
          "algorithm": "",
          "header": "",
          "secret": "",
          "allowed_clock_skew": 0,
          "error_code": 0,
          "error_message": ""
        }
      },
      "coprocess": {
        "use_param": false,
        "param_name": "",
        "use_cookie": false,
        "cookie_name": "",
        "auth_header_name": "Authorization",
        "use_certificate": false,
        "validate_signature": false,
        "signature": {
          "algorithm": "",
          "header": "",
          "secret": "",
          "allowed_clock_skew": 0,
          "error_code": 0,
          "error_message": ""
        }
      },
      "hmac": {
        "use_param": false,
        "param_name": "",
        "use_cookie": false,
        "cookie_name": "",
        "auth_header_name": "Authorization",
        "use_certificate": false,
        "validate_signature": false,
        "signature": {
          "algorithm": "",
          "header": "",
          "secret": "",
          "allowed_clock_skew": 0,
          "error_code": 0,
          "error_message": ""
        }
      },
      "jwt": {
        "use_param": false,
        "param_name": "",
        "use_cookie": false,
        "cookie_name": "",
        "auth_header_name": "Authorization",
        "use_certificate": false,
        "validate_signature": false,
        "signature": {
          "algorithm": "",
          "header": "",
          "secret": "",
          "allowed_clock_skew": 0,
          "error_code": 0,
          "error_message": ""
        }
      },
      "oauth": {
        "use_param": false,
        "param_name": "",
        "use_cookie": false,
        "cookie_name": "",
        "auth_header_name": "Authorization",
        "use_certificate": false,
        "validate_signature": false,
        "signature": {
          "algorithm": "",
          "header": "",
          "secret": "",
          "allowed_clock_skew": 0,
          "error_code": 0,
          "error_message": ""
        }
      },
      "oidc": {
        "use_param": false,
        "param_name": "",
        "use_cookie": false,
        "cookie_name": "",
        "auth_header_name": "Authorization",
        "use_certificate": false,
        "validate_signature": false,
        "signature": {
          "algorithm": "",
          "header": "",
          "secret": "",
          "allowed_clock_skew": 0,
          "error_code": 0,
          "error_message": ""
        }
      }
    },
    "strip_auth_data": false,
    "id": "6219068a95210c0001771abe",
    "certificates": [],
    "enable_signature_checking": false,
    "use_openid": false,
    "internal": false,
    "jwt_skip_kid": false,
    "enable_batch_request_support": false,
    "enable_detailed_recording": false,
    "response_processors": [],
    "use_mutual_tls_auth": false
  }

Test Policy 1: Manages Test API 1 using per API

{
    "auth_type": "authToken",
    "auth_types": [
        "authToken"
    ],
    "state": "active",
    "graphql_enabled": false,
    "_id": "621906eb95210c0001771abf",
    "id": "",
    "name": "Test Policy 1",
    "org_id": "5e9d9544a1dcd60001d0ed20",
    "rate": -1,
    "per": -1,
    "quota_max": -1,
    "quota_renewal_rate": -1,
    "throttle_interval": -1,
    "throttle_retry_limit": -1,
    "max_query_depth": -1,
    "access_rights": {
        "c82f9012376a43ee6ea88fca3107729b": {
            "api_name": "Test API 1",
            "api_id": "c82f9012376a43ee6ea88fca3107729b",
            "versions": [
                "Default"
            ],
            "allowed_urls": [],
            "restricted_types": [],
            "limit": {
                "rate": 5,
                "per": 60,
                "throttle_interval": -1,
                "throttle_retry_limit": -1,
                "max_query_depth": -1,
                "quota_max": -1,
                "quota_renews": 0,
                "quota_remaining": 0,
                "quota_renewal_rate": -1,
                "set_by_policy": false
            },
            "field_access_rights": [],
            "allowance_scope": ""
        }
    },
    "hmac_enabled": false,
    "active": true,
    "is_inactive": false,
    "date_created": "2022-02-25T16:42:19.602Z",
    "tags": [],
    "key_expires_in": 0,
    "partitions": {
        "quota": false,
        "rate_limit": false,
        "complexity": false,
        "acl": false,
        "per_api": true
    },
    "last_updated": "1645807343",
    "meta_data": {}
}

Test Policy 2: Manages Test API 2 using per API

{
    "auth_type": "authToken",
    "auth_types": [
        "authToken"
    ],
    "state": "active",
    "graphql_enabled": false,
    "_id": "6219070f95210c0001771ac0",
    "id": "",
    "name": "Test Policy 2",
    "org_id": "5e9d9544a1dcd60001d0ed20",
    "rate": -1,
    "per": -1,
    "quota_max": -1,
    "quota_renewal_rate": -1,
    "throttle_interval": -1,
    "throttle_retry_limit": -1,
    "max_query_depth": -1,
    "access_rights": {
        "3f484ed934f24bb548b57a93e00b2262": {
            "api_name": "Test API 2",
            "api_id": "3f484ed934f24bb548b57a93e00b2262",
            "versions": [
                "Default"
            ],
            "allowed_urls": [],
            "restricted_types": [],
            "limit": {
                "rate": 10,
                "per": 60,
                "throttle_interval": -1,
                "throttle_retry_limit": -1,
                "max_query_depth": -1,
                "quota_max": -1,
                "quota_renews": 0,
                "quota_remaining": 0,
                "quota_renewal_rate": -1,
                "set_by_policy": false
            },
            "field_access_rights": [],
            "allowance_scope": ""
        }
    },
    "hmac_enabled": false,
    "active": true,
    "is_inactive": false,
    "date_created": "2022-02-25T16:42:55.64Z",
    "tags": [],
    "key_expires_in": 0,
    "partitions": {
        "quota": false,
        "rate_limit": false,
        "complexity": false,
        "acl": false,
        "per_api": true
    },
    "last_updated": "1645807375",
    "meta_data": {}
}

Finally you will just need to create the key based on both policies. The areas to highlight as @Olu mentioned are the partitions section in each policy,

    "partitions": {
        "quota": false,
        "rate_limit": false,
        "complexity": false,
        "acl": false,
        "per_api": true
    },

the limit section under the access_rights object,

             "limit": {
                "rate": 10,
                "per": 60,
                "throttle_interval": -1,
                "throttle_retry_limit": -1,
                "max_query_depth": -1,
                "quota_max": -1,
                "quota_renews": 0,
                "quota_remaining": 0,
                "quota_renewal_rate": -1,
                "set_by_policy": false
            },

And finally global limits on the policy object

    "rate": -1,
    "per": -1,
    "quota_max": -1,
    "quota_renewal_rate": -1,
    "throttle_interval": -1,
    "throttle_retry_limit": -1,
    "max_query_depth": -1,

The reason to why merging the other polices was not working was because both polices were setting the global limit and one was overriding the other. Turning off the global limits will prevent setting a global limit for the key, and setting the per key limits allows you to manage the limits for those keys. I hope this helps.

@zaid @Olu Thankyou for support, recently I understood why this issue was occurring and the probable solution for it.
But it was really great to hear same thing from you guys and get more clarification it.

Thanks have a great day!

1 Like