Flag architecture
Eliya's flags are organised into two layers with distinct purposes. This page explains the taxonomy: what each layer does, why the syntaxes differ, and when to reach for which.
Two layers, two syntaxes
Eliya's flag namespace is split into two layers that match different concerns. The two layers use different Hotspot flag syntaxes that match their semantic structure, the same pattern Hotspot itself uses (-XX:NativeMemoryTracking=summary for enums, -XX:+HeapDumpOnOutOfMemoryError for toggles). Capabilities give fine-grained control; the profile gives a curated combination. Each layer is documented below.
Layer 1: Capabilities
Each capability flag activates a single, narrowly-scoped technical concern. Capabilities are composable: you set multiple capability flags to assemble custom configurations. Capability flags use boolean syntax:
Note. The capability flag names above are reserved namespace: UseEliyaObservability, UseEliyaDiagnostics, UseEliyaOperational, and UseEliyaTooling become operational in Phase 2; UseEliyaSecurityStrict and UseEliyaAudit in Phase 4. Phase 1 ships the profile flag only; the example is shown here to illustrate the boolean syntax pattern.
Capabilities are what the JVM does. They are the source of truth.
Layer 2: Profile
A single profile selector specifies which curated combination is active. Profiles are mutually exclusive by design; only one profile can be active at a time. EliyaProfile is an enum-valued flag holding a single value at runtime; the JVM cannot be in a state of "two profiles active simultaneously." When customer demand requires the union of two frameworks (e.g., PCI DSS + HIPAA for healthcare payment processing), Eliya ships an explicit combined profile (e.g., EliyaProfile=Healthcare-Payment) with the documented union of capabilities, rather than allowing operators to stack two profile values. Profile flag uses enum-value syntax:
Profiles serve compliance officers and engineers who want known-good combinations rather than building from primitives. Each profile activates a documented set of underlying capabilities plus framework-specific settings.
Phase 1: what's available today
Phase 1 ships a single profile and reserves the capability namespace for Phase 2. The profile is the canonical way to activate Eliya's defaults; capability flags are documented but not yet carved out as separate booleans.
Available now
| Flag | Layer | Effect |
|---|---|---|
-XX:EliyaProfile=Production | Layer 2: profile | Activates production-readiness defaults. Phase 1 (today): heap-dump-on-OOM with structured path, exit-on-OOM, Native Memory Tracking summary, predictable crash log path, container support reinforced, diagnostic VM options unlocked. Phase 2 adds continuous JFR and unified GC logging. |
-XX:EliyaProfile=None | Layer 2: profile | Explicit no-profile (default). Compose capabilities directly when they ship in Phase 2. |
-XX:+EliyaConflictCheck | Control flag | Enable startup-time detection of flag conflicts (default: enabled). Three-tier response: silent / warning / fatal. |
Full per-component breakdown of what EliyaProfile=Production activates: see the flags reference.
Reserved namespace (Phase 2 + Phase 4)
The following capability flags and profile values are reserved. They are not implemented in Phase 1, but the namespace is locked so future work cannot collide with these names.
Layer 1 capabilities (Phase 2 + Phase 4)
| Capability flag | Phase | Purpose |
|---|---|---|
UseEliyaObservability | Phase 2 | Continuous data collection (JFR, GC logs, NMT) |
UseEliyaDiagnostics | Phase 2 | Incident-time artifact capture (heap dumps, crash logs) |
UseEliyaOperational | Phase 2 | Operational policy (ExitOnOOM, container support) |
UseEliyaTooling | Phase 2 | Foundation flags for diagnostic tools |
UseEliyaSecurityBaseline | Phase 4 | Modest security hardening beyond upstream |
UseEliyaSecurityStrict | Phase 4 | Aggressive security hardening |
UseEliyaAudit | Phase 4 | Audit-grade logging extensions |
Layer 2 profile values (Phase 4 demand-gated)
| Profile value | Purpose |
|---|---|
EliyaProfile=PCIDSS | PCI DSS-aligned compliance settings |
EliyaProfile=HIPAA | HIPAA-aligned compliance settings |
EliyaProfile=SOX | SOX-aligned compliance settings |
EliyaProfile=FedRAMP | FedRAMP-aligned compliance settings |
EliyaProfile=GDPR | GDPR-aligned data handling settings |
EliyaProfile=ISO27001 | ISO 27001-aligned settings |
EliyaProfile=SOC2 | SOC 2-aligned settings |
Phase 4 profile values produce a startup error in Phase 1: "Profile '<Value>' is reserved for Phase 4. Currently available: None, Production."
Combined profiles
Some regulated industries require the union of multiple compliance frameworks: healthcare payment processors need PCI DSS + HIPAA, financial SaaS providers need SOC 2 + ISO 27001, defence contractors need FedRAMP + CMMC. For these cases, Eliya ships explicit combined profile values rather than allowing operators to stack two profile flags. Example combined values (Phase 4 demand-gated, naming illustrative):
| Combined profile value | Component frameworks | Typical audience |
|---|---|---|
EliyaProfile=Healthcare-Payment | PCI DSS + HIPAA | Healthcare payment processors |
EliyaProfile=Financial-SaaS | SOC 2 + ISO 27001 | Financial services SaaS providers |
EliyaProfile=Federal-Defense | FedRAMP + CMMC | Defence contractors handling federal workloads |
Each combined profile activates the documented union of capabilities from its component frameworks plus any framework-specific JVM settings the combination requires. The auditor sees one profile name in asymm --info output, the capability list is documented, and compliance attribution is unambiguous. Combined profiles are designed by Asymm Systems based on customer demand rather than left to ad-hoc stacking.
Demand signal for Phase 4: join the early-access list on the security page and tell us which framework (or combination) your auditor requires.
Conflict detection: three response tiers
Eliya checks flag combinations at JVM startup and responds in one of three tiers depending on the conflict's severity. Default behaviour is checking enabled; opt out via -XX:-EliyaConflictCheck only when experimenting with flag combinations or running CI matrix tests where intentional invalid combinations are part of the test plan. Leave enabled in production.
Note on examples. The tier examples below illustrate the conflict-detection framework using capability flags (UseEliyaObservability, UseEliyaSecurityStrict) and profile values (PCIDSS) that are reserved for Phase 2 and Phase 4. The framework itself is implemented in Phase 1; the capability flags it references begin shipping in Phase 2. Phase 1 ships the profile flag (EliyaProfile=Production) and the conflict-check control flag only.
Tier 1: Silent resolution
User explicit command-line settings override profile-implied defaults. This is established Hotspot override semantics; no warning issued.
Profile activates observability; user explicit -UseEliyaObservability wins. Intentional override; no warning.
Tier 2: Warning
Suspicious-but-legal combinations produce a warning to stderr. The JVM continues normally.
java -XX:EliyaProfile=Production -XX:+UseEliyaObservability -jar app.jar
[Eliya] Warning: EliyaProfile=Production already activates UseEliyaObservability;
explicit flag is redundant. Tier 3: Fatal exit
Genuinely incompatible combinations cause JVM startup to fail with a descriptive error. Compliance environments require fail-fast on misconfiguration; the alternative (silent misbehaviour discovered during a production incident) is operationally worse than refusing to start.
java -XX:EliyaProfile=PCIDSS -XX:-UseEliyaSecurityStrict -jar app.jar
[Eliya] Fatal: EliyaProfile=PCIDSS requires UseEliyaSecurityStrict;
cannot proceed with explicit -UseEliyaSecurityStrict. Either drop the
profile (-XX:EliyaProfile=None), remove the explicit negation, or
compose underlying capabilities directly without the profile shortcut. Why two layers, why dual syntax
Why two layers
Single-layer alternatives fail in different ways. Capabilities-only is hostile to non-expert users; nobody wants to research five flags to deploy production-ready Eliya. Profiles-only is hostile to advanced users; latency-sensitive teams might want diagnostics without observability, and a pre-built-only menu denies them control. Two layers serve both audiences with the same architecture.
Why dual syntax
The syntax matches the semantics:
- "Is observability enabled?": boolean question →
+/-syntax - "Which profile is active?": enumeration question →
=syntax
This produces three real benefits beyond aesthetic match:
- Profile state is single-valued.
EliyaProfileis accstrflag, so the runtime state holds exactly one value. If duplicate arguments appear on the command line, the parser takes the last one (typical Hotspot value-flag behaviour). No state in the JVM represents "two profiles active simultaneously," which means Eliya's conflict detection can focus on profile-plus-capability conflicts rather than profile-vs-profile. - Visual layer distinction is immediate. Anyone scanning JVM args knows from the syntax alone whether they're looking at a capability or a profile.
- Native Hotspot compilation. Both flag forms map to standard Hotspot macros in
globals.hpp; no custom parser, no macro hacking. Same C++ compilation path asUseG1GCandNativeMemoryTracking.
Diagnostic path layout
When the Production profile is active (or when Phase 2 capability flags that activate diagnostic output are set), Eliya constructs filesystem paths from three resolved components:
${ELIYA_DIAGNOSTIC_PATH}/${service_name}/${replica_name}/${category}/ Base path, configurable: ELIYA_DIAGNOSTIC_PATH env var → platform default (Linux: /var/log/eliya).
Service name, logical service identity: ELIYA_SERVICE_NAME → -Deliya.service.name= → HOSTNAME → literal default.
Replica name, per-instance identity: ELIYA_REPLICA_NAME → -Deliya.replica.name= → HOSTNAME → suppressed when equal to ${service_name}.
Category, Eliya-controlled, one of: jfr, heap, crash, gc.
The suppression rule
When the resolved replica name equals the resolved service name, the replica level is suppressed and the path collapses to two levels (${base}/${service}/${category}/). Two specific cases:
- Bare-metal multi-JVM hosts. Three systemd services on
myserver01, each settingELIYA_SERVICE_NAMEto its service name.HOSTNAMEismyserver01for all of them. Without suppression, paths would include redundant/myserver01/myserver01/nesting that adds no attribution value. - Single-JVM bare-metal. Nothing configured. Service falls through to
HOSTNAME. Replica also resolves toHOSTNAME. They match. Suppression collapses to a single${hostname}/level.
In Kubernetes deployments, HOSTNAME is the pod name (unique per pod), and you typically set ELIYA_SERVICE_NAME to the service-level name. These differ, so suppression doesn't apply and three-level paths result.
Why three levels
The layout encodes compliance metadata in the filesystem itself: service grouping (compliance queries scoped to a service return a single tree), per-replica attribution (each subdirectory's name identifies the pod/container/unit that produced its contents), lifetime disambiguation (PID-bearing filenames within each replica directory distinguish multiple JVM processes across the replica's lifetime), and tool compatibility (flat per-replica layout works with logrotate, fluentd, vector, journald, and standard audit-pipeline tooling).
For deployment-by-deployment effective path examples (Kubernetes single- and multi-replica, bare-metal multi-JVM, docker-compose scale, explicit replica naming), see flags reference: diagnostic paths.