ksqlDB
ksqlDB stream/table model, persistent query, pull/push query, materialized view, joins, aggregation, schema integration, scaling, and operational risk for enterprise Kafka systems.
Part 021 — ksqlDB
ksqlDB is often introduced as “SQL on Kafka.” That description is useful for onboarding, but it is dangerously incomplete for production architecture.
A better mental model is this:
ksqlDB is a stream processing runtime that lets you define Kafka stream/table transformations using SQL-like syntax, backed by Kafka topics, Schema Registry integration, internal processing state, and long-running persistent queries.
It is not a normal relational database. It is not a replacement for PostgreSQL. It is not merely a dashboard query engine. It is not a harmless convenience layer. In an enterprise Java/JAX-RS system, ksqlDB can become a production dependency that owns derived data, query semantics, operational failure modes, scaling behavior, and schema compatibility risks.
This part focuses on how a senior backend engineer should reason about ksqlDB in systems involving Kafka, PostgreSQL, MyBatis/JDBC, microservices, Kubernetes, AWS/Azure/on-prem deployments, and CPQ/order-management style workflows.
1. Core Concept
ksqlDB allows teams to create continuous stream processing queries over Kafka topics using SQL-like statements.
Typical use cases include:
- filtering an event stream
- projecting event payloads into a simplified shape
- joining streams and tables
- aggregating events by key
- creating materialized views
- enriching events
- deriving operational/event-driven read models
- exploring Kafka topics interactively
- building lightweight streaming transformations without writing a Java Kafka Streams application
The important point: ksqlDB does not execute a query once and finish. Many ksqlDB queries are persistent. They keep running, continuously reading from Kafka topics and writing derived results to other Kafka topics or materialized state.
2. Why ksqlDB Exists
Kafka stores ordered streams of records. Kafka alone does not provide high-level declarative transformation semantics. Without ksqlDB, teams usually write custom consumers or Kafka Streams applications to transform, join, aggregate, and materialize data.
ksqlDB exists to provide a declarative interface over Kafka Streams-like processing.
It helps when:
- transformation logic is simple enough to express in SQL-like form
- the team wants quick stream-derived topics
- operational teams need Kafka-native materialized views
- event exploration is needed without writing a full Java service
- stream processing should be managed separately from business microservices
- the organization already has Kafka, Schema Registry, and production support around streaming workloads
It becomes risky when:
- teams treat it as a general-purpose database
- business-critical logic is hidden in ad-hoc SQL queries
- query ownership is unclear
- schema compatibility is weak
- stateful queries are not monitored
- pull queries become an API dependency without proper SLOs
- derived topics are created without lifecycle governance
3. ksqlDB Mental Model
A ksqlDB deployment usually consists of:
- ksqlDB server nodes
- Kafka cluster
- Kafka topics used as sources and sinks
- Schema Registry if Avro/Protobuf/JSON Schema is used
- persistent queries
- internal Kafka Streams applications behind the scenes
- state stores for tables/materialized views
- query metadata
- CLI, REST API, or UI access
When you create a persistent query, ksqlDB starts a long-running streaming application. That application consumes from source topics, applies transformations, and writes to sink topics or materialized state.
From a production perspective, a ksqlDB query is not “just SQL.” It is a deployed streaming workload.
4. Stream and Table Model
ksqlDB uses the stream/table duality inherited from stream processing theory and Kafka Streams.
Stream
A stream is an unbounded sequence of immutable events.
Example interpretation:
QuoteCreated
QuoteSubmitted
QuoteApproved
OrderCreated
OrderActivated
OrderCancelled
Each record represents something that happened.
A stream is useful when:
- every event matters
- append-only history matters
- consumers should process each occurrence
- event order has meaning
- the system models transitions or facts over time
Table
A table represents the latest known value for a key.
Example interpretation:
quote_id -> latest quote status
order_id -> latest order lifecycle state
customer_id -> latest customer profile snapshot
product_id -> latest catalog snapshot
A table is useful when:
- lookup by key matters
- latest state matters more than every transition
- enrichment is needed
- joins require current state
- materialized view semantics are desired
Important distinction
A stream answers:
What happened?
A table answers:
What is the latest known state?
Confusing these two is a common source of incorrect event-driven design.
5. Persistent Query
A persistent query continuously processes data.
Conceptually:
CREATE STREAM approved_quotes AS
SELECT *
FROM quote_events
WHERE event_type = 'QuoteApproved'
EMIT CHANGES;
This creates a running stream processing job that reads from quote_events and writes approved quote records to another Kafka topic.
Production implications:
- the query has lifecycle
- the query can fail
- the query can lag
- the query can be restarted
- the query can create internal state
- the query can create sink topics
- query changes may require migration
- downstream services may depend on its output
A persistent query should be treated like deployable application logic, not like a disposable SQL snippet.
6. Pull Query
A pull query reads from a materialized table.
Conceptually:
SELECT *
FROM quote_status_table
WHERE quote_id = 'Q-123';
This looks like a database query, but the backing state is maintained by Kafka stream processing.
Pull queries can be useful for:
- operational lookup
- debugging
- serving low-volume state lookups
- building internal tools
- checking derived state
But they require caution if exposed to production APIs.
Risk areas:
- availability depends on ksqlDB
- data freshness depends on stream lag
- query latency may not match relational database expectations
- indexing options are limited compared with PostgreSQL
- query semantics are tied to key-based access
- scaling and HA must be engineered
For Java/JAX-RS services, avoid casually replacing PostgreSQL read models with ksqlDB pull queries unless the runtime SLO, operational ownership, and failure behavior are explicit.
7. Push Query
A push query subscribes to ongoing changes.
Conceptually:
SELECT *
FROM order_events
WHERE order_id = 'O-456'
EMIT CHANGES;
Push queries can be useful for:
- live event inspection
- operational monitoring
- streaming UI/internal diagnostics
- reactive status updates
They are less appropriate as a default backend API mechanism unless the team has intentionally designed for streaming responses, connection management, authorization, backpressure, and lifecycle control.
In a JAX-RS backend, using push queries directly from HTTP endpoints is usually a design smell unless carefully constrained.
8. Materialized Views
A materialized view in ksqlDB is derived state built from Kafka topics.
Example conceptual flow:
quote-events topic
-> ksqlDB aggregation/query
-> quote-status materialized table
-> pull query / downstream topic
Materialized views are powerful because they let you create queryable state from event streams.
But they introduce consistency and ownership questions:
- Who owns the view?
- Who owns the query definition?
- Who owns schema compatibility?
- What is the freshness SLO?
- What happens if the view is wrong?
- Can the view be rebuilt?
- Can downstream services tolerate lag?
- Is the view used for decision-making, display, audit, or integration?
For CPQ/order management, materialized views may be useful for status summaries or operational dashboards, but business-critical write decisions should be carefully reviewed before relying on derived state.
9. Join Semantics
ksqlDB supports stream-stream, stream-table, and table-table style joins, depending on the query type and source definitions.
The major concern is not syntax. The concern is semantics.
Questions to ask:
- Are both sides keyed correctly?
- Are events co-partitioned?
- Is repartitioning happening implicitly?
- Is the join window correct?
- What happens to late events?
- What happens when one side is missing?
- Is the join deterministic under replay?
- Does the join produce duplicates?
- What is the business meaning of the join result?
Example risk:
OrderCreated joins latest CustomerProfile.
This may sound reasonable, but the result depends on timing. If customer profile changes later, should the order enrichment reflect the original profile at order time or the latest profile at processing time?
That is not a SQL problem. That is a domain semantics problem.
10. Aggregation and Windowing
ksqlDB can aggregate events by key and time window.
Common examples:
- orders per customer per hour
- quote submissions per tenant per day
- approval failures per product family
- fallout events per downstream integration
- DLQ events per service
- pricing recalculation events per catalog version
Windowing requires explicit reasoning:
- event time vs processing time
- tumbling window vs hopping window vs session window
- late event tolerance
- grace period
- suppression behavior
- duplicate event impact
- replay behavior
- aggregation state size
In enterprise systems, windowed aggregation often becomes part of operational analytics or alerting. That means correctness and freshness must be understood.
11. Connector Integration
ksqlDB can integrate with Kafka Connect in some environments to create source/sink connectors or work with connector-managed topics.
This can be attractive:
PostgreSQL -> Debezium/Kafka Connect -> Kafka topic -> ksqlDB -> derived topic -> sink connector
But the operational chain becomes longer:
- PostgreSQL WAL/logical decoding
- Debezium connector
- Kafka topic
- Schema Registry
- ksqlDB persistent query
- sink topic
- sink connector
- target system
Each step has offsets, errors, schemas, lag, retries, and failure handling.
If this pipeline supports customer-impacting behavior, it needs a runbook and ownership model.
12. Schema Registry Integration
ksqlDB commonly works with Schema Registry-backed data formats such as Avro, Protobuf, or JSON Schema.
Important concerns:
- source topic schema compatibility
- sink topic schema generation
- subject naming strategy
- schema evolution over time
- enum evolution
- optional/required field changes
- field rename and removal
- compatibility mode
- schema IDs in serialized payloads
- query breakage due to schema changes
A ksqlDB query is a consumer of schemas and often a producer of new schemas. Therefore, it participates in event contract governance.
Do not let ksqlDB become a schema bypass.
13. Query Lifecycle
A production ksqlDB query should have lifecycle states similar to application deployments.
Useful lifecycle model:
Draft
-> Reviewed
-> Tested
-> Deployed to lower environment
-> Validated
-> Promoted
-> Monitored
-> Changed
-> Deprecated
-> Removed
For every persistent query, track:
- owner
- purpose
- source topics
- sink topics
- schema dependencies
- expected throughput
- stateful/stateless nature
- downstream consumers
- freshness SLO
- replay/rebuild process
- rollback strategy
- monitoring dashboard
- alert policy
If persistent queries are created manually in production, config drift is almost guaranteed.
14. Scaling ksqlDB
ksqlDB scaling depends on the underlying Kafka topic partitioning and query topology.
Scaling considerations:
- source topic partition count
- sink topic partition count
- consumer group behavior
- query parallelism
- state store distribution
- repartition topics
- RocksDB/state storage if applicable
- Kubernetes pod resources
- CPU throttling
- memory pressure
- disk I/O for stateful queries
- network throughput
- restore time after restart
Adding more ksqlDB nodes does not magically improve every query. Parallelism is constrained by topic partitions and topology design.
For stateful queries, scaling can trigger rebalance and state movement. This can cause lag spikes and restore delays.
15. ksqlDB vs Kafka Streams
ksqlDB and Kafka Streams overlap, but they are not the same operational choice.
ksqlDB is often better when:
- transformation logic is simple
- SQL-like declarative syntax improves speed
- the workload is platform-owned
- a small number of well-governed derived streams/tables are needed
- operational SQL-based exploration is valuable
Kafka Streams is often better when:
- business logic is complex
- strong testing and code review are required
- integration with Java domain code is needed
- custom error handling is required
- advanced state management is needed
- deployment should follow normal service lifecycle
- the team wants explicit type-safe code
Decision rule:
Use ksqlDB for declarative streaming transformations that are simple, governed, observable, and operationally owned. Use Kafka Streams or custom consumers when logic becomes domain-heavy, test-heavy, or operationally specialized.
16. ksqlDB vs PostgreSQL View
A PostgreSQL view operates over relational database tables. A ksqlDB materialized view operates over Kafka stream-derived state.
They solve different problems.
Use PostgreSQL views/materialized views when:
- source of truth is relational
- strong transactional consistency is needed
- query flexibility matters
- SQL joins over normalized relational state are needed
- the API already depends on PostgreSQL
Use ksqlDB when:
- source of truth is Kafka event streams
- data should be derived continuously
- event replay/rebuild is part of the model
- the derived state is naturally keyed by event stream data
- transformation sits in the streaming layer
Anti-pattern:
Replacing a well-understood PostgreSQL read model with ksqlDB only because the source data eventually appears in Kafka.
That can increase latency, operational complexity, and correctness risk.
17. ksqlDB Operational Risk
ksqlDB operational risks include:
- persistent query failure
- query lag
- state store corruption or slow restoration
- schema incompatibility
- source topic retention too short for rebuild
- sink topic misconfiguration
- repartition topic growth
- incorrect join/window semantics
- query deployment drift
- manual production changes
- unowned materialized views
- pull query overload
- hidden business logic outside application repositories
- weak observability
A senior engineer should treat every production ksqlDB query as a workload with SLO, owner, versioning, and rollback procedure.
18. When to Use ksqlDB
Use ksqlDB when most of these are true:
- transformation is understandable in SQL-like syntax
- source and sink topics are governed
- schemas are registered and compatible
- persistent query ownership is clear
- output is not an opaque hidden dependency
- operational dashboards exist
- replay/rebuild is understood
- lower-environment testing exists
- deployment is automated or at least controlled
- failure does not silently corrupt critical business state
Good examples:
- operational filtering topics
- lightweight derived event streams
- event enrichment with well-defined tables
- streaming metrics aggregation
- internal operational materialized views
- non-critical exploratory transformations that later graduate to governed workloads
19. When Not to Use ksqlDB
Avoid ksqlDB when:
- logic is complex and domain-heavy
- correctness requires sophisticated tests
- output drives irreversible business actions
- query ownership is unclear
- schema governance is weak
- operational team cannot support it
- pull queries are expected to behave like a high-SLA OLTP database
- event timing semantics are unclear
- joins require nuanced domain reasoning
- data privacy/access control is not solved
- the query exists only because “SQL is easier than code”
A declarative query can still create production incidents.
20. Java/JAX-RS Impact
ksqlDB affects Java/JAX-RS services in several ways.
As an upstream derived topic producer
A Java service may consume a topic produced by ksqlDB.
Review concerns:
- Is the ksqlDB query owned and versioned?
- Is the output schema governed?
- Is output ordering understood?
- Is output replay-safe?
- What happens if the query lags or stops?
As a query dependency
A Java service may call ksqlDB pull queries.
Review concerns:
- Is this part of request path?
- What is the latency SLO?
- What is the fallback behavior?
- Is stale data acceptable?
- How are auth and tenant boundaries enforced?
As an operational tool
A team may use ksqlDB for debugging.
Review concerns:
- Who has access?
- Is PII exposed?
- Are queries audited?
- Can users create accidental heavy queries?
21. PostgreSQL/MyBatis/JDBC Impact
ksqlDB often sits downstream of PostgreSQL CDC or outbox topics.
Important concerns:
- PostgreSQL is still source of truth for transactional state
- Debezium/outbox topics may feed ksqlDB
- schema changes in PostgreSQL may affect CDC topics
- outbox payload shape may affect query stability
- replay from Kafka may rebuild derived state but not PostgreSQL state
- MyBatis transaction boundaries remain independent from ksqlDB processing
Never assume ksqlDB materialized state has the same consistency guarantees as PostgreSQL transaction state.
22. Kubernetes/AWS/Azure/On-Prem Impact
ksqlDB deployment should be reviewed like any other stateful/streaming platform component.
In Kubernetes:
- pod resource limits matter
- restarts trigger query rebalancing/restoration
- state directories may need persistent or ephemeral strategy depending on deployment
- readiness probes should reflect useful availability
- rolling updates can cause lag spikes
- network policies must allow Kafka and Schema Registry access
In cloud-managed environments:
- check managed ksqlDB availability if using Confluent Cloud or equivalent
- check networking/private endpoint constraints
- check identity/auth integration
- check service limits
- check billing/capacity behavior
On-prem/hybrid:
- certificate and DNS issues are common
- bandwidth between Kafka and ksqlDB matters
- operational ownership must be explicit
- upgrades require compatibility planning
23. Failure Modes
Common ksqlDB failure modes:
| Failure | Likely Symptom | Common Cause | Risk |
|---|---|---|---|
| Persistent query stopped | Output topic no longer updates | Query failure, schema error, runtime issue | Stale downstream data |
| Query lag increasing | Delayed output | Slow processing, resource pressure, source spike | SLA breach |
| Schema incompatibility | Query fails after schema change | Breaking schema evolution | Pipeline outage |
| Join result wrong | Missing or duplicated output | Wrong key/window/table semantics | Business inconsistency |
| Pull query slow | API/debug tool timeout | State/store/resource issue | Operational impact |
| State restore slow | Long recovery after restart | Large state store, insufficient resources | Extended outage |
| Repartition topic growth | Disk/storage pressure | Query topology repartitions data | Capacity incident |
| Manual query drift | Different env behavior | Ad-hoc production changes | Undebuggable pipeline |
24. Detection and Debugging
When a ksqlDB issue occurs, debug from symptom to topology.
Suggested flow:
1. Identify affected output topic/table.
2. Identify persistent query producing it.
3. Check query status.
4. Check source topic lag and input rate.
5. Check ksqlDB server logs.
6. Check schema registry compatibility errors.
7. Check sink topic creation/config.
8. Check internal repartition/changelog topics.
9. Check resource usage: CPU, memory, disk, network.
10. Check recent query/schema/topic deployments.
11. Validate sample records from source and sink.
12. Confirm downstream consumer impact.
Avoid immediately restarting ksqlDB without understanding whether the issue is schema, state, resource pressure, or query logic.
25. Production Review Checklist
Use this checklist before approving a production ksqlDB workload.
Query semantics
- Is this a stream, table, or materialized view?
- Is the key correct?
- Is the join/window logic correct?
- Are late events handled?
- Is replay deterministic?
- Are duplicates acceptable or handled?
Ownership
- Who owns the query?
- Who owns source topics?
- Who owns sink topics?
- Who responds to incidents?
- Where is the query definition stored?
Schema
- Are schemas registered?
- Is compatibility enforced?
- Is sink schema reviewed?
- Are breaking changes blocked?
Operations
- Is lag monitored?
- Is query status monitored?
- Are resource limits sufficient?
- Is restart behavior understood?
- Is restore time acceptable?
- Is there a runbook?
Security/privacy
- Does the query expose PII?
- Are pull queries access-controlled?
- Are headers/payloads logged safely?
- Is tenant isolation preserved?
Integration with Java/JAX-RS
- Is any API request path dependent on ksqlDB?
- Is stale data acceptable?
- Is fallback behavior defined?
- Is the response contract honest about eventual consistency?
26. Internal Verification Checklist
Verify the following in the actual organization/team context before assuming ksqlDB behavior:
- Whether ksqlDB is used at all.
- Whether it is self-managed, cloud-managed, or not approved for production use.
- Where persistent query definitions are stored.
- Whether query deployment is manual, CI/CD-managed, or GitOps-managed.
- Which source topics are consumed by ksqlDB.
- Which sink topics are produced by ksqlDB.
- Whether Schema Registry is integrated.
- Whether pull queries are used by Java/JAX-RS services.
- Whether ksqlDB output drives business workflows or only analytics/ops use cases.
- Whether query lag dashboards exist.
- Whether state store restoration is monitored.
- Whether query changes require architecture review.
- Whether PII/privacy review applies to ksqlDB topics and queries.
- Whether incident runbooks exist for query failure, schema breakage, and lag.
27. Senior Engineer Heuristics
Use these heuristics during review:
- If a ksqlDB query creates a topic consumed by services, treat it as production application logic.
- If a pull query is in the API request path, demand clear SLO and fallback behavior.
- If query logic encodes business rules, ask why it is not in versioned, tested application code.
- If a join is involved, review event-time semantics and key alignment carefully.
- If stateful aggregation is involved, review restoration time and changelog retention.
- If schema evolution is weak, ksqlDB will eventually break.
- If ownership is unclear, do not approve business-critical dependency.
- If output can be replayed, prove consumers are replay-safe.
28. Key Takeaways
ksqlDB is powerful because it makes stream processing accessible through SQL-like declarations.
Its danger is the same: it can make production stream processing look easier than it is.
A senior backend engineer should understand that ksqlDB queries are not harmless scripts. They are long-running distributed processing workloads with schema, state, ownership, lag, scaling, security, and failure behavior.
Use ksqlDB when it simplifies governed streaming transformations. Avoid it when it hides critical business logic, bypasses testing, or creates operational dependencies nobody owns.
You just completed lesson 21 in build core. Use the series map if you want to review the broader track, or continue directly into the next lesson while the context is still warm.
Keep the momentum while the lesson is still fresh. Move backward for review or continue forward into the next concept.