Starter
Nine 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 (9 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: partitions must be in [1, 2, 3, 6, 12] (override via labels.partition-override-approved=true) rules: - condition: '(has(metadata.labels) && "partition-override-approved" in metadata.labels && metadata.labels["partition-override-approved"] == "true") || spec.partitions in [1, 2, 3, 6, 12]' errorMessage: "Partitions must be one of [1, 2, 3, 6, 12] (set label partition-override-approved=true to request an override)" --- 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: max-retention-bound spec: targetKind: Topic description: retention.ms must be <= 30d and not infinite, unless labels.retention-justified == "true" rules: - condition: '(has(metadata.labels) && "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: topic-compression-passthrough spec: targetKind: Topic description: compression.type on the topic must be "producer" (or unset). Compression is enforced producer-side via Gateway. rules: - condition: '!has(spec.configs) || !("compression.type" in spec.configs) || spec.configs["compression.type"] == "producer"' errorMessage: "compression.type must be \"producer\" (or unset) — broker recompression wastes CPU. Enforce lz4/zstd at the producer via the Gateway producer-compression-required interceptor." --- apiVersion: gateway/v2 kind: Interceptor metadata: name: schema-id-required-on-produce scope: vCluster: passthrough spec: pluginClass: io.conduktor.gateway.interceptor.safeguard.SchemaPayloadValidationPolicyPlugin priority: 100 config: topic: "^(?!__|_).+$" schemaIdRequired: true validateSchema: false action: BLOCK schemaRegistryConfig: host: "${SR_URL}" type: CONFLUENT --- apiVersion: self-serve/v1 kind: ResourcePolicy metadata: name: no-wildcard-acl-prod spec: targetKind: ApplicationGroup description: ApplicationGroups cannot grant wildcard resource permissions (name="*") regardless of patternType rules: - condition: 'spec.permissions.all(p, p.name != "*")' errorMessage: "Wildcard resource name=\"*\" is not allowed (LITERAL or PREFIXED) — scope by an explicit prefix instead" --- 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
2Partitions
1Replication
1Retention
1Compression
1Schema Enforcement
1Security & ACLs
1Resource Limits
1Enforce 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 →