Backend
There are two implementations that execute EQL, and only one ever runs at runtime.
| Backend | Role | When |
|---|---|---|
| Aster CEP | Default · Reference Implementation | General installation |
| Flink | Oracle — Not for production use | Used to contrast answers for the same statement |
The selection criterion is the installation scale. General installations use Aster CEP, and Flink is designated for large-scale streaming — however, it is not deployed for production today.
Aster CEP does not define the language. The scope of the language is determined by the common IR, and Aster CEP is the implementation that executes it most broadly. Features are not removed from the language simply because Flink cannot support them.
Aster CEP is a CEP engine developed and maintained by KOPENS. It implements the continuous quantifier (* + ? {n,m}) of SQL:2016 MATCH_RECOGNIZE within the engine, and the expected values were contrasted with Flink 2.3.0.
How to Select — A Single Line
A single line in plantpulse-cep.properties selects both the planner and the runtime.
cep.backend=aster # aster | flink
| Value | Meaning |
|---|---|
aster | Default — Aster CEP |
flink | Oracle — Not for production use |
| Not configured | Defaults to aster |
If it silently reverted to a default, the running version would differ from what the operator selected, and that discrepancy would remain invisible until the results became abnormal.
The same applies to cep.backend=esper — this value does not exist. Please refer to the Upgrade Notes.
cep.mode — How to «Query» Portability
#cep.mode=native # native | portable. 설정하지 않으면 native
| Mode | Registration Condition |
|---|---|
native (Default) | Registered if the booted backend accepts it. Features unique to that engine may be used |
portable | Must be accepted by the booted backend and backends in the portable set |
The portable set consists only of Aster CEP (Flink is an Oracle and thus outside the set). Therefore, in an installation booted with Aster CEP, portable has no further place to query and is identical to native.
Whether a statement is portable is not declared in a table — it is actually queried to the backend's planner. Declarations age, but queries do not.
If rejected, it is recorded which backend rejected it and due to which configuration.
portable requires the planner to be queried to exist in the buildIf absent, the gate refuses to run entirely instead of «measuring with what it has». Half-measured portability is worse than not measuring at all.
What Runs Where — Capability Matrix
The answers from the two backends are managed as artifacts. This is a table created by feeding a golden corpus into both planners; a commit that moves a cell must also move that table to pass.
| Aster CEP (Reference) | Flink (Oracle) | |
|---|---|---|
| ✓ out of 127 actual language cases | 106 | 53 |
How to read:
| Symbol | Meaning |
|---|---|
| ✓ | Planner generated a plan (For Aster CEP, the actual engine went through compilation) |
| ✗ Token | Rejected by naming the reason |
| — | The language could not implement it — not an answer from the engine |
— means the language does not know that configuration, and ✗ means the language knows it, but this engine cannot run it. The operator's actions differ — for the former, the statement must be rewritten; for the latter, that configuration must be removed.
Typical Divergence Points Between the Two Backends
| Configuration | Aster CEP | Flink |
|---|---|---|
pattern[...] | ✅ | Partial |
Absence Pattern not X for 30 min | ✅ | ❌ |
MATCH_RECOGNIZE Base form | ✅ | ✅ |
〃 SKIP PAST LAST ROW | ❌ | ✅ |
〃 Alternating A | B · PERMUTE | ❌ | ✅ |
JOIN | ✅ | ❌ |
DISTINCT | ✅ (Conditional) | ❌ |
ORDER BY · LIMIT | ✅ | ❌ |
Unary NOT | ✅ | ❌ |
INSERT INTO | ✅ | ❌ |
WINDOW TUMBLING … ALIGN TO FIRST EVENT | ✅ | ❌ |
WINDOW SLIDING | ✅ | ❌ |
The full table in the product repository's capability matrix is the authoritative version. The above is a summary of frequently encountered points.
The Flink Switch is Only Meaningful When Booted with Flink
cep.flink.reconciler.enabled=false
cep.flink.router.enabled=false
This is a defect experienced in actual operation — it was started with Aster CEP, but because these two were on, the same statement ran in two engines and results were sent twice.
Currently, if the boot backend is not Flink, it is ignored and its name is logged once. However, it is better to clean up the value itself — the next person will not know it is being ignored.