Kong: a custom plugin is a handler, a schema and a rockspec

handler.lua holds the logic, schema.lua declares and validates the configuration, and the plugin name must be listed in kong.conf before Kong will load it.

Code
-- kong/plugins/my-plugin/schema.lua
return {
  name = "my-plugin",
  fields = {
    { config = {
        type = "record",
        fields = {
          { tenant = { type = "string", required = true } },
          { timeout = { type = "number", default = 1000, between = { 1, 60000 } } },
        },
    }},
  },
}

# kong.conf
plugins = bundled,my-plugin
lua_package_path = /opt/kong-plugins/?.lua;;
Output
# Validation happens at configuration time, not at request time:
#   curl -X POST localhost:8001/plugins --data name=my-plugin
#   HTTP/1.1 400 Bad Request
#   {"fields":{"config":{"tenant":"required field missing"}}}
#
# Check what Kong parsed from your schema:
#   curl -s localhost:8001/schemas/plugins/my-plugin | jq
#
# Omitting the plugin from `plugins` in kong.conf is the usual reason a
# correctly written plugin "does not exist".
Advertisement

Run this yourself in the Online Java Compiler, spin up a live REST API in the API Sandbox, or practise with Java interview questions.

Published 2026-08-25