conduktor.io ↗

Starter

Ten essentials. Start here if you have nothing in place today.

Why this bundle

The baseline governance pack.

Ten policies covering naming, replication, retention, and compression. Apply this if you have nothing in place today. It blocks the config mistakes that cause most incidents without getting in any team's way.

Apply the whole bundle

One concatenated YAML stream with every ResourcePolicy in this bundle. Copy, save, apply.

# All policies in the Starter bundle (10 resources)
# Save as bundle-starter.yaml then: conduktor apply -f bundle-starter.yaml
# Each ResourcePolicy must still be linked via Application(Instance).spec.policyRef
# or KafkaCluster.spec.policiesRef to take effect.
---
apiVersion: self-serve/v1
kind: ResourcePolicy
metadata:
  name: topic-name-convention
spec:
  targetKind: Topic
  description: Topic names must follow <env>.<domain>.<entity>.<version>
  rules:
    - condition: metadata.name.matches("^(dev|staging|prod)\\.[a-z0-9-]+\\.[a-z0-9-]+\\.v[0-9]+$")
      errorMessage: "Topic name must match <env>.<domain>.<entity>.<version> (e.g. prod.orders.placed.v1)"
---
apiVersion: self-serve/v1
kind: ResourcePolicy
metadata:
  name: consumer-group-prefix
spec:
  targetKind: ApplicationGroup
  description: Consumer-group / ApplicationGroup names must be <team>.<app>.cg
  rules:
    - condition: metadata.name.matches("^[a-z][a-z0-9-]+\\.[a-z0-9-]+\\.cg$")
      errorMessage: "Consumer group must be <team>.<app>.cg (e.g. orders.fraud-detector.cg)"
---
apiVersion: self-serve/v1
kind: ResourcePolicy
metadata:
  name: partition-count-bounds
spec:
  targetKind: Topic
  description: Topics must have between 1 and 200 partitions
  rules:
    - condition: spec.partitions >= 1 && spec.partitions <= 200
      errorMessage: "Partitions must be between 1 and 200 (request an override for outliers)"
---
apiVersion: self-serve/v1
kind: ResourcePolicy
metadata:
  name: min-replication-factor
spec:
  targetKind: Topic
  description: Production topics must have replication factor >= 3
  rules:
    - condition: '!metadata.name.startsWith("prod.") || spec.replicationFactor >= 3'
      errorMessage: "Production topics must have replication factor >= 3"
---
apiVersion: self-serve/v1
kind: ResourcePolicy
metadata:
  name: isr-alignment
spec:
  targetKind: Topic
  description: min.insync.replicas must equal replicationFactor - 1
  rules:
    - condition: '"min.insync.replicas" in spec.configs && int(string(spec.configs["min.insync.replicas"])) == int(spec.replicationFactor) - 1'
      errorMessage: "min.insync.replicas must equal replicationFactor - 1 (e.g. RF=3 -> min.insync.replicas=2)"
---
apiVersion: self-serve/v1
kind: ResourcePolicy
metadata:
  name: max-retention-bound
spec:
  targetKind: Topic
  description: retention.ms must be <= 30d and not infinite, unless labels.retention-justified == "true"
  rules:
    - condition: '("retention-justified" in metadata.labels && metadata.labels["retention-justified"] == "true") || ("retention.ms" in spec.configs && int(string(spec.configs["retention.ms"])) != -1 && int(string(spec.configs["retention.ms"])) <= 2592000000)'
      errorMessage: "retention.ms must be <= 30 days and not -1 (set label retention-justified=true to override)"
---
apiVersion: self-serve/v1
kind: ResourcePolicy
metadata:
  name: compression-allowlist
spec:
  targetKind: Topic
  description: compression.type must be lz4 or zstd
  rules:
    - condition: '"compression.type" in spec.configs && spec.configs["compression.type"] in ["lz4", "zstd"]'
      errorMessage: "compression.type must be lz4 or zstd"
---
apiVersion: self-serve/v1
kind: ResourcePolicy
metadata:
  name: schema-required-non-internal
spec:
  targetKind: Topic
  description: Non-internal topics must declare a schema subject via labels.schema-subject
  rules:
    - condition: 'metadata.name.startsWith("__") || metadata.name.startsWith("_") || ("schema-subject" in metadata.labels && size(metadata.labels["schema-subject"]) > 0)'
      errorMessage: "Non-internal topics must set label schema-subject=<subject-name> (or be Schema-Registry-governed)"
---
apiVersion: self-serve/v1
kind: ResourcePolicy
metadata:
  name: no-wildcard-acl-prod
spec:
  targetKind: ApplicationGroup
  description: ApplicationGroups touching prod.* resources cannot use wildcard LITERAL resource patterns
  rules:
    - condition: 'spec.permissions.all(p, !(p.name.startsWith("prod.") || p.name == "*") || (p.patternType != "LITERAL" || p.name != "*"))'
      errorMessage: "Wildcard LITERAL resource is not allowed on production resources"
---
apiVersion: self-serve/v1
kind: ResourcePolicy
metadata:
  name: max-message-bytes-bound
spec:
  targetKind: Topic
  description: max.message.bytes must be <= 10 MB
  rules:
    - condition: '!("max.message.bytes" in spec.configs) || int(string(spec.configs["max.message.bytes"])) <= 10485760'
      errorMessage: "max.message.bytes > 10 MB — consider claim-check pattern with S3"

Each policy must still be linked via Application(Instance).spec.policyRef or KafkaCluster.spec.policiesRef to take effect.

Policies in this bundle

Grouped by category. Click any policy for the rationale, examples, and YAML.

Naming

2

Partitions

1

Replication

2

Retention

1

Compression

1

Schema Enforcement

1

Security & ACLs

1

Resource Limits

1

Enforce this bundle automatically?

Drop these YAMLs into Conduktor Console to get central enforcement, audit history, and pre-commit feedback for every change.

See Conduktor Console →