RFC: Kong native Declarative Config format


Hi everyone,

We are in the process of designing a native declarative configuration format to be used in Kong.
Declarative config — specifying your full configuration in a declarative way, rather than an imperative sequence of Admin API operations — has been a desire from the community for a while. A number of features that we want to eventually have depend on having a way to specify a full Kong configuration: defining the declarative config format is the foundational step to get there.

Declarative config has been on our radar for a while, and our first stab at it was decK, an external declarative config tool. With the experience gained with this project, we’ve been working on the idea of a native declarative config format. We’d like to share with the you all our current work-in-progress design, in order to gather community feedback.

Kong Declarative Config Format (latest update 2019-02-20)

The format will be presented below in YAML, but it will be supported in JSON as well. At this point we do not have a formal specification, but we will present the intended feature set through a complete commented example:

# Metadata fields start with an underscore (_)
# Fields that do not start with an underscore represent Kong entities and attributes

# Matches Kong minimum version that supports the format
_format_version: "1.1"

# YAML supports comments, but JSON doesn't. Our format
# supports the "_comment" field in the top-level and within entities
_comment: "general comment about the file"

# The top-level and entities also support the "_ignore" field,
# which keeps an array of entries that are ignored by Kong.
# You can use it to store your additional metadata.
- my_own_data: 123
- foo: bar
  kong_ignores: "all of this"

# Each Kong entity (core entity or custom entity introduced by a plugin)
# can be listed in the top-level as an array of objects:
- name: my-service
  url: http://mockbin.org
  # Entities will be able to store tags as metadata
  tags: [desktop, example]
  # Entities that have a foreign-key relationship can be nested:
  - name: example-route
    # Each entity has its own, optional, set of tags
    tags: [desktop, something_else]
    - example.test
    # Plugins applied to example-route:
    - name: basic-auth
  # Plugins applied to my-service:
  - name: key-auth

- name: my-route
  # Relationships can also be specified between top-level entities,
  # either by name or by id
  service: my-service
  hosts: ["hello.com"]

- username: Frodo
  # Custom entities from plugin can also be specified
  # If they specify a foreign-key relationshp, they can also be nested
  - key: my-key
  - name: rate-limiting
    _comment: "these are default rate-limits for user Frodo"
      second: 5
      hour: 10000

# When an entity has multiple foreign-key relationships
# (e.g. a plugin matching on both consumer and service)
# it must be specified as a top-level entity, and not through
# nesting.
- name: rate-limiting
  consumer: Frodo
  service: my-service
  _comment: "Frodo is extra limited when using my-service"
    hour: 100
  # tags are for your organization only and have no meaning for Kong:
  - extra_limits
  - my_tag 

We are trying to keep a good balance between functionality an simplicity. Please let us know your impressions!


Seems fine to me. As with no db I imagine certain plugins like OAuth2 with client credentials flow through Kong would be unsupported and only a local rate limiting policy applied and things of that nature but overall it provides a solid way to cut out the db.

Other aspects I think will be doing it in a manner that does not require an actual redeploy/restart and parse of a local yaml file sitting on the Kong node itself, but rather can each node point to a schema file hosted remotely at a central location possibly and do some sort of kong rebuild -f https://myrepo.com/mykongrepo/kongconfig.yaml at runtime with no downtime? And then just run that cmd on every declarative kong node we run to keep them in sync? Ofc a local file should be reasonable too if thats how a user wants to do it :slight_smile: , but I would prefer one remote yaml file hosted elsewhere and say my 6 kong nodes all reference that one yaml.

Other random features floating in my head would be a way to maybe encrypt/decrypt the kong config file for some potential use case I haven’t fully vetted(share the file/keep it visible in public repo but not expose secrets stored in plaintext maybe? idk, maybe just add a layer of encryption on just the secrets in a way only Kong cluster “declarative” nodes would be able to decipher.).

If I have any other ideas i will drop them in place. I probably, won’t be leveraging this flow anytime soon due to being unable to support oauth2 cc by nature, but I do like the idea of it! Not being tied to a db and latency/connections held around that would provide a large amount of stability and not cut down too many features.


@hisham can we provide an example of declaring an entity with a long, complex string value (e.g., a certificates object)?


Very cool. Wonderful to see this WIP Draft!

Curious what is the underlying plan for how this config is used by Kong:

Will it be read at start-up, and the config loaded into the backing datastore like API-based configuration? In other words, can this declarative config be mixed with API-based config, or are they exclusive to one another?


Hi Hisham,

Wondering if more than one file should be used. This helps to keep environment related details away from route definitions. Something like this:

  • consumer.yml
  • route.yml
  • service.yml

A single file containing all configurations is harder to manage.

We have developed an internal declarative configuration tool for Kong along similar lines which is working well so far.


This is very similar to the format we came up with for kongverge, except it’s in YAML :smiley:


For those who use k8s ingress for declarative configuration already, would this proposal dovetail with that work at all?

There are plenty of situations where a user will want to test the same set of routes and services as they have in k8s in a local development environment. This RFC would allow them to create that local dev environment declaratively. However, they’ll end up with the same rules defined in k8s ingress definitions and in this RFC’s config format, won’t they. Is there a way we could avoid the duplication?


Yes, that’s the idea. For rate-limiting, one can also use the redis backend (effectively having a separate datastore just for that).

As for the usage workflow, in the first iteration we’re planning to provide an endpoint for (re-)uploading the configuration file, as well as a kong.conf option for specifying the file at startup (which can be overriden via env vars as usual).

Our initial plan is for this declarative file format to be used in both database-backend and DB-less scenarios:

  • when using a database, the file can be used for bulk import (essentially every item gets upserted on top of the current configuration)
  • when using db-less, the file is a truly declarative configuration: i.e. it represents the entire state of the world for Kong, so pushing a new one means the old configuration is discarded and replaced by the new one entirely.

We do have plans for that (and it’s helpful to hear that it’s a desired feature!) but the first release will probably be a single file.

We plan supporting both YAML and JSON; the conversion from one to the other is the one you expect (the _comment metadata field was added for the sake of JSON).

We will certainly look into this. We are constantly making steps to have the K8s experience for Kong to be as seamless as possible.


Sure. YAML provides syntax for that; this is a part of a generated config produced by our test suite testing mesh-related functionality using declarative config:

- pk: true
  key: |
    -----BEGIN PRIVATE KEY-----
    -----END PRIVATE KEY-----
  cert: |
    -----END CERTIFICATE-----

Note that in this first iteration we’re not tackling the issue of securing any secrets in the config file (the format accepts in principle any core or plugin entity and configuration); at this point the user’s workflow will have to take this into consideration.


Thank you all for your feedback! We now have a PR open implementing the first iteration of the declarative config features, aiming for Kong 1.1: