Data centers — power & cooling
The problem. A data center's two biggest risks are heat and the power bill. A cooling unit that quietly fails lets a row of racks climb toward thermal shutdown; meanwhile cooling and power overhead — everything not spent on actual compute — is the largest controllable cost. Facilities teams need to catch a thermal problem before racks throttle, and to drive overhead down by seeing exactly where the watts go.
What we solve here is preventing heat-related outages and cutting the energy that never reaches a server.
Set up demo data
New workspace? Run this once (Python) to create a rack's inlet-temperature series, create the subscription before we listen (with a hot spell), and the rack→cooling graph — so step 3 finds the shared unit. Safe to re-run.
import datahub_sdk, numpy as np, pandas as pd
client = datahub_sdk.DataHubClient.from_env()
client.timeseries.create([datahub_sdk.TimeSeries(external_id="rack_r14_inlet_temp_c", name="Rack R14 inlet temp", unit="deg_c", value_type="float")])
client.subscriptions.create([datahub_sdk.Subscription(
external_id="hall_2_thermal", name="Hall 2 thermal", timeseries=["rack_r14_inlet_temp_c"])])
idx = pd.date_range(end=pd.Timestamp.now(tz="UTC"), periods=60, freq="1min")
t = np.full(60, 24.0); t[-10:] = 29.4 # above the 27 °C band
client.timeseries.insert_from_lists(timestamps=idx, values=t, ts="rack_r14_inlet_temp_c")
client.resources.create(
[datahub_sdk.Resource(external_id=x, name=x, labels=[lbl]) for x, lbl in
[("rack_r14", "Rack"), ("rack_r15", "Rack"), ("crac_unit_2", "Crac")]],
[datahub_sdk.RelForm.by_external_ids("rack_r14", "crac_unit_2", "cooled_by"),
datahub_sdk.RelForm.by_external_ids("rack_r15", "crac_unit_2", "cooled_by")])
1. Catch a thermal problem early
Rack inlet temperatures and cooling-unit status stream live. When inlet temperature
climbs past the safe band, raise a thermal_warning so the team intervenes before
hardware protects itself by shutting down. See Consume live data.
- Java
- Python
- Rust
import ai.intellistream.datahub.sdk.subscriptions.SubscriptionMessage;
try (var stream = client.subscriptions().listen(List.of("hall_2_thermal"))
.stream((SubscriptionMessage msg) -> { // auto-acks after each message
if (inletAbove(msg.payload(), 27.0)) { // °C — above ASHRAE band
EventModel warning = new EventModel();
warning.setExternalId("thermal_warning_r14_" + System.currentTimeMillis());
warning.setType("thermal_warning");
warning.setStatus("open");
warning.setMetadata(Map.of("rack", "rack_r14", "inlet_c", "29.4"));
warning.setEventTime(ZonedDateTime.now());
client.events().create(List.of(warning));
}
})) {
awaitShutdown(); // your app lifecycle; closing the stream ends delivery
}
with client.subscriptions.listen(["hall_2_thermal"]) as listener:
for msg in listener:
if inlet_above(msg.payload, 27.0): # °C — above ASHRAE band
client.events.create([datahub_sdk.Event(
external_id=f"thermal_warning_r14_{int(pd.Timestamp.now().timestamp())}",
type="thermal_warning", status="open",
event_time=pd.Timestamp.now(tz="UTC"),
metadata={"rack": "rack_r14", "inlet_c": "29.4"})])
listener.ack([msg.message_id])
use dataplatform_rust_sdk::events::Event;
use chrono::Utc;
let mut listener = api.subscriptions.listen(&["hall_2_thermal"]).await?;
while let Some(Ok(msg)) = listener.next().await {
if inlet_above(&msg.payload, 27.0) { // °C — above ASHRAE band
let mut warning = Event::new(format!("thermal_warning_r14_{}", Utc::now().timestamp()));
warning.r#type = Some("thermal_warning".into());
warning.status = Some("open".into());
warning.add_metadata("rack".into(), "rack_r14".into());
warning.add_metadata("inlet_c".into(), "29.4".into());
warning.set_event_time(Utc::now());
api.events.create(&vec![warning]).await?;
}
listener.ack(&[msg.message_id.as_str()]).await?;
}
2. Drive down overhead (PUE)
PUE is total facility power over IT power. Roll both meters up to hourly sums, divide, and the trend shows whether a cooling tweak actually helped. See Query & aggregate.
3. When racks overheat together, find the cooling unit
Several racks climbing at once usually means one shared cooling unit, not a coincidence. Model racks → CRAC units as a graph and walk from each hot rack to the unit they share — the exact two-alarms-one-cooling-system pattern.
- Java
- Python
- Rust
ResourceNetwork a = client.resources().fetchRelated("rack_r14", 3);
ResourceNetwork b = client.resources().fetchRelated("rack_r15", 3);
Set<String> aNodes = a.nodes().stream().map(Resource::getExternalId).collect(Collectors.toSet());
Set<String> shared = b.nodes().stream().map(Resource::getExternalId)
.filter(aNodes::contains).collect(Collectors.toSet());
// shared contains "crac_unit_2" → one failing unit, not two hot racks
a = client.resources.fetch_related(external_id="rack_r14", depth=3)
b = client.resources.fetch_related(external_id="rack_r15", depth=3)
shared = {n.external_id for n in a.nodes} & {n.external_id for n in b.nodes}
# 'crac_unit_2' in shared → one failing unit
use dataplatform_rust_sdk::resources::RelatedResourcesForm;
use std::collections::HashSet;
let a = api.resources.fetch_related(
&RelatedResourcesForm::from_external_id("rack_r14").with_depth(3)).await?;
let b = api.resources.fetch_related(
&RelatedResourcesForm::from_external_id("rack_r15").with_depth(3)).await?;
let an: HashSet<&str> = a.nodes().iter().map(|n| n.external_id.as_str()).collect();
let shared: Vec<&str> = b.nodes().iter()
.map(|n| n.external_id.as_str()).filter(|id| an.contains(id)).collect();
// shared contains "crac_unit_2"
See the result
The hot rack trips the loop, and the two warming racks share one cooling unit:
thermal_warning raised for rack_r14
shared unit: crac_unit_2 ← one failing CRAC, not two hot racks
See also
- Consume live data — the thermal-monitoring loop.
- Query & aggregate — the PUE trend.
- Correlate alarms with the graph — find the shared cooling unit.