Hazelcast Jet is a distributed stream and batch processing engine embedded in the Hazelcast Platform. Since Hazelcast Platform 5.0, Jet is the stream processing layer of a unified in-memory computing platform — the same JVM cluster that serves your distributed caches and IMaps also runs your streaming pipelines. Jet processes data as DAGs of vertices, provides exactly-once guarantees via distributed snapshotting, and uses Hazelcast IMap for blazing-fast in-memory state. But when a cluster member leaves, a snapshot fails, or a Jet job enters a failure loop, you need to know before it cascades into downstream data loss. Vigilmon gives you the HTTP-based health checks, heartbeats, and alerting to cover every critical dimension of your Hazelcast Platform / Jet deployment.
What You'll Set Up
- Hazelcast cluster member count monitoring
- Jet job status health checks
- Distributed snapshot success rate alerting
- IMap memory usage monitoring
- Kafka source consumer group lag alerts
- Processing throughput tracking
- JVM heap and GC pause monitoring
- Split-brain quorum protection alerts
- Hazelcast Management Center / REST API health
- Jet job restart frequency tracking
Prerequisites
- Hazelcast Platform 5.0+ running as a JVM cluster (bare metal, Docker, or Kubernetes)
- Hazelcast REST API enabled (
hazelcast.rest.enabled: truein your config) - Hazelcast Management Center (optional but recommended)
- A free Vigilmon account
Why Monitor Hazelcast Jet?
Hazelcast Platform's distributed nature means that failures are often partial and silent. A single member leaving the cluster degrades processing throughput without stopping the pipeline — until the cluster drops below quorum and Jet suspends all jobs. Distributed snapshots are your exactly-once guarantee; if they start failing, you are silently downgrading to at-least-once. IMap state that fills up the JVM heap causes GC pressure that cascades into processing stalls and then member crashes. And a Jet job that enters a failure-restart loop drains cluster resources and may never recover without operator intervention. Proactive Vigilmon monitoring surfaces all of these before they become incidents.
Step 1: Monitor Hazelcast Cluster Member Count
Hazelcast's REST API exposes cluster state including member count. Enable the REST API in your hazelcast.yaml:
hazelcast:
rest-api:
enabled: true
endpoint-groups:
CLUSTER_READ:
enabled: true
CLUSTER_WRITE:
enabled: true
HEALTH_CHECK:
enabled: true
The health check endpoint is available at:
http://<member-host>:5701/hazelcast/health
This returns a simple 200 OK with body Hazelcast::NodeState=ACTIVE when the member is healthy. Add a Vigilmon monitor:
- Click Add Monitor → HTTP / HTTPS.
- Enter
http://<member-host>:5701/hazelcast/health. - Set Expected HTTP status to
200. - Optionally set Expected body contains to
ACTIVE. - Set Check interval to
1 minute. - Click Save.
Add one monitor per member. For the cluster member count, query the cluster state endpoint:
http://<member-host>:5701/hazelcast/rest/cluster
This returns JSON with {"members":["<uuid>","<uuid>"],"state":"ACTIVE"}. Write a small proxy that parses this and returns 503 when members.length < MIN_MEMBERS:
// Spring Boot probe example
@RestController
public class ClusterProbe {
@Value("${hazelcast.rest.url}")
private String hazelcastUrl;
@Value("${cluster.min.members:3}")
private int minMembers;
@GetMapping("/probe/cluster")
public ResponseEntity<Map<String,Object>> clusterHealth() throws Exception {
String json = restTemplate.getForObject(hazelcastUrl + "/rest/cluster", String.class);
JSONObject obj = new JSONObject(json);
int count = obj.getJSONArray("members").length();
String state = obj.getString("state");
boolean healthy = count >= minMembers && "ACTIVE".equals(state);
return ResponseEntity.status(healthy ? 200 : 503)
.body(Map.of("member_count", count, "state", state, "min_members", minMembers));
}
}
Monitor http://<probe-host>:8080/probe/cluster in Vigilmon. Alert on 503 immediately — member loss directly impacts processing capacity.
Step 2: Monitor Jet Job Health
Jet jobs run as long-lived distributed computations. A failed job stops processing; a suspended job stops accumulating results. Poll job status via the Hazelcast REST API:
GET http://<member>:5701/hazelcast/rest/jets/jobs
This returns a list of jobs with their statuses: RUNNING, SUSPENDED, FAILED, COMPLETED. Write a probe that returns 503 if any expected job is not RUNNING:
@GetMapping("/probe/jet-jobs")
public ResponseEntity<Map<String,Object>> jetJobHealth() throws Exception {
String json = restTemplate.getForObject(hazelcastUrl + "/rest/jets/jobs", String.class);
JSONArray jobs = new JSONArray(json);
List<Map<String,Object>> failed = new ArrayList<>();
for (int i = 0; i < jobs.length(); i++) {
JSONObject job = jobs.getJSONObject(i);
String status = job.getString("status");
if (!"RUNNING".equals(status) && !"COMPLETED".equals(status)) {
failed.add(Map.of("name", job.getString("name"), "status", status));
}
}
boolean healthy = failed.isEmpty();
return ResponseEntity.status(healthy ? 200 : 503)
.body(Map.of("failed_jobs", failed, "total_jobs", jobs.length()));
}
Add a Vigilmon monitor at /probe/jet-jobs with a 1-minute interval. A FAILED job is an immediate alert; a SUSPENDED job warrants investigation.
Step 3: Monitor Distributed Snapshot Health
Hazelcast Jet uses distributed snapshotting (similar to Flink checkpointing) to provide exactly-once and at-least-once guarantees. Failed snapshots mean state is not persisted and a crash would cause reprocessing from the last successful snapshot.
Monitor snapshot events via the Management Center REST API or JMX. If you have Management Center:
GET http://<mc-host>:8080/api/rest/clusters/<cluster-name>/jet/snapshot-stats
For a lightweight alternative, expose a probe that checks the last snapshot timestamp per job:
// Use HazelcastInstance.getJet().getJob(jobId).getSuspensionCause() and
// metrics APIs to detect snapshot failures
@GetMapping("/probe/snapshots")
public ResponseEntity<Map<String,Object>> snapshotHealth() {
// Query Hazelcast metrics for: jet.snapshotting.completed.count
// and jet.snapshotting.failed.count via the /metrics endpoint
long failed = getMetricValue("jet.snapshotting.failed.count");
long completed = getMetricValue("jet.snapshotting.completed.count");
boolean healthy = failed == 0;
return ResponseEntity.status(healthy ? 200 : 503)
.body(Map.of("snapshots_failed", failed, "snapshots_completed", completed));
}
Hazelcast exposes Prometheus-compatible metrics at:
http://<member>:8080/metrics
(requires hazelcast.metrics.prometheus.enabled: true). Add a Vigilmon monitor. Alert on any 503 — snapshot failures silently degrade your delivery guarantee.
Step 4: Monitor IMap State Memory Usage
Jet uses Hazelcast IMap for stateful processing. When IMap memory usage exceeds cluster heap, members start evicting entries or crashing with OutOfMemoryError.
Use the REST API to check IMap statistics:
GET http://<member>:5701/hazelcast/rest/maps/<map-name>/stats
Write a probe that computes used heap percentage:
@GetMapping("/probe/imap-memory")
public ResponseEntity<Map<String,Object>> imapMemoryHealth() throws Exception {
// Get total heap across all members
String clusterJson = restTemplate.getForObject(hazelcastUrl + "/rest/cluster", String.class);
// Get IMap heap cost
String mapJson = restTemplate.getForObject(hazelcastUrl + "/rest/maps/jet-state/stats", String.class);
JSONObject stats = new JSONObject(mapJson);
long heapCost = stats.getLong("heapCost");
long maxHeap = Runtime.getRuntime().maxMemory();
double pct = (double) heapCost / maxHeap * 100;
boolean healthy = pct < 80.0;
return ResponseEntity.status(healthy ? 200 : 503)
.body(Map.of("heap_used_pct", pct, "heap_cost_bytes", heapCost));
}
Alert on 503 (heap > 80%) — IMap memory pressure cascades quickly into GC issues and member crashes.
Step 5: Monitor Kafka Source Consumer Group Lag
Jet's Kafka source connector maintains a consumer group. Growing lag means Jet is not keeping up with the Kafka topic's message rate.
Expose a Kafka lag endpoint alongside your Jet cluster (see the pattern from the Bytewax tutorial). Return 200 when lag is below threshold, 503 when it exceeds it:
@GetMapping("/probe/kafka-lag")
public ResponseEntity<Map<String,Object>> kafkaLagHealth() {
long lag = kafkaLagService.getTotalLag("jet-consumer-group");
long threshold = 10000L;
boolean healthy = lag < threshold;
return ResponseEntity.status(healthy ? 200 : 503)
.body(Map.of("total_lag", lag, "threshold", threshold));
}
Monitor at /probe/kafka-lag with a 1-minute interval.
Step 6: Monitor Processing Throughput
Hazelcast Jet exposes a jet.items.out metric per vertex. Query the Prometheus metrics endpoint for throughput:
http://<member>:8080/metrics
Look for jet_items_out_total and compute a rate. Write a probe that compares the current rate against a baseline:
@GetMapping("/probe/throughput")
public ResponseEntity<Map<String,Object>> throughputHealth() {
double itemsPerSec = metricsService.getJetItemsOutRate();
double baselineItemsPerSec = 50_000; // set from historical average
double threshold = baselineItemsPerSec * 0.7;
boolean healthy = itemsPerSec >= threshold;
return ResponseEntity.status(healthy ? 200 : 503)
.body(Map.of("items_per_sec", itemsPerSec, "threshold", threshold));
}
Alert on 503 — a sudden throughput drop usually indicates a member leaving, a job being suspended, or Kafka lag building up.
Step 7: Monitor JVM Heap and GC Pause Duration
Hazelcast Platform runs on the JVM. Long GC pauses (>5 seconds) cause heartbeat timeouts between members and can trigger false split-brain detection. Expose JVM health via a Spring Boot Actuator endpoint:
management:
endpoints:
web:
exposure:
include: health,metrics
metrics:
export:
prometheus:
enabled: true
Or write a custom probe:
@GetMapping("/probe/jvm")
public ResponseEntity<Map<String,Object>> jvmHealth() {
MemoryMXBean mem = ManagementFactory.getMemoryMXBean();
long used = mem.getHeapMemoryUsage().getUsed();
long max = mem.getHeapMemoryUsage().getMax();
double pct = (double) used / max * 100;
long maxGcPauseMs = getMaxRecentGcPauseMs(); // from GarbageCollectorMXBean
boolean healthy = pct < 85 && maxGcPauseMs < 5000;
return ResponseEntity.status(healthy ? 200 : 503)
.body(Map.of("heap_used_pct", pct, "max_gc_pause_ms", maxGcPauseMs));
}
private long getMaxRecentGcPauseMs() {
return ManagementFactory.getGarbageCollectorMXBeans().stream()
.mapToLong(gc -> gc.getCollectionTime())
.max()
.orElse(0L);
}
Monitor at /probe/jvm with a 1-minute interval. Alert on 503 — a GC pause >5 seconds can cascade into cluster instability.
Step 8: Monitor Split-Brain Protection
Hazelcast uses quorum (split-brain protection) rules to prevent cluster partitions from operating independently. When a partition happens, Hazelcast freezes the minority partition.
Monitor the cluster state via the REST API:
GET http://<member>:5701/hazelcast/rest/cluster
Parse the state field: ACTIVE is normal; FROZEN or PASSIVE indicates split-brain protection has activated. Write a probe:
@GetMapping("/probe/split-brain")
public ResponseEntity<Map<String,Object>> splitBrainHealth() throws Exception {
String json = restTemplate.getForObject(hazelcastUrl + "/rest/cluster", String.class);
JSONObject obj = new JSONObject(json);
String state = obj.getString("state");
boolean healthy = "ACTIVE".equals(state);
return ResponseEntity.status(healthy ? 200 : 503)
.body(Map.of("cluster_state", state));
}
Alert on 503 immediately — a frozen cluster stops processing all Jet jobs.
Step 9: Monitor Hazelcast Management Center Health
Management Center is the primary operational interface for Hazelcast Platform. If it goes down, your team loses visibility into cluster health, job status, and IMap statistics.
Management Center exposes a health endpoint:
GET http://<mc-host>:8080/health
Add a Vigilmon monitor:
- Click Add Monitor → HTTP / HTTPS.
- Enter
http://<mc-host>:8080/health. - Set Expected HTTP status to
200. - Set Check interval to
1 minute. - Click Save.
Also monitor the Hazelcast REST API directly to catch cases where Management Center is up but has lost cluster connectivity:
GET http://<member>:5701/hazelcast/health
Step 10: Track Jet Job Restart Frequency
A Jet job that restarts more than 3 times in one hour is in a failure loop. Instrument job restart events and expose a restart rate endpoint:
// Implement a JobStateListener (Hazelcast Jet API)
public class RestartTracker implements JobStatusListener {
private final Deque<Long> restartTimestamps = new ConcurrentLinkedDeque<>();
@Override
public void jobStatusChanged(JobStatusEvent event) {
if (event.getNewStatus() == JobStatus.RUNNING && event.getPreviousStatus() == JobStatus.STARTING) {
long now = System.currentTimeMillis();
restartTimestamps.addLast(now);
// evict entries older than 1 hour
while (!restartTimestamps.isEmpty() && restartTimestamps.peekFirst() < now - 3_600_000) {
restartTimestamps.pollFirst();
}
}
}
public int restartsInLastHour() {
return restartTimestamps.size();
}
}
Expose a probe returning 503 when restartsInLastHour() > 3:
@GetMapping("/probe/job-restarts")
public ResponseEntity<Map<String,Object>> jobRestartHealth() {
int restarts = restartTracker.restartsInLastHour();
boolean healthy = restarts <= 3;
return ResponseEntity.status(healthy ? 200 : 503)
.body(Map.of("restarts_last_hour", restarts, "threshold", 3));
}
Monitor at /probe/job-restarts. A job in a restart loop needs manual intervention to resolve the root cause.
Alerting Configuration
| Monitor | Condition | Action |
|---------|-----------|--------|
| Cluster member health | Any 503 or non-ACTIVE state | Page on-call immediately |
| Jet job status | Any 503 (job not RUNNING) | Page on-call immediately |
| Snapshot health | Any 503 (snapshot failure) | Page on-call immediately |
| IMap memory | 503 (heap > 80%) | Notify platform team |
| Kafka source lag | 503 (lag > threshold) | Notify data engineering team |
| Processing throughput | 503 (dropped > 30%) | Notify data engineering team |
| JVM / GC health | 503 (GC > 5s or heap > 85%) | Page on-call immediately |
| Split-brain | 503 (cluster not ACTIVE) | Page on-call immediately |
| Management Center | Any 503 | Notify platform team |
| Job restart rate | 503 (>3 restarts/hour) | Notify data engineering team |
Route alerts to PagerDuty, Slack, or email using Vigilmon's Notification Channels.
Conclusion
Hazelcast Jet's in-memory, JVM-based architecture is extremely fast — but it means failures are often abrupt and silent. A member crash, a snapshot failure, or a GC pause can cascade through the cluster in seconds. Vigilmon's HTTP health checks, applied to a lightweight probe sidecar alongside your Hazelcast members, give you real-time visibility into the ten critical health dimensions: cluster member count, job status, snapshot integrity, IMap memory pressure, Kafka source lag, throughput, JVM health, split-brain protection, Management Center reachability, and job restart loops. With the right alerts wired up, you catch degradation in seconds rather than minutes.
Get started free at vigilmon.online.