Skip to content

We run this ourselves. You can watch it break.

Grow2FIT operates a full reference implementation of the platform we design for clients — Kubernetes, GitOps, secrets and monitoring — on our own infrastructure. It runs every day, including the nights nobody is watching. And because the environment is ours, we can push a service into failure while you watch and let it recover: the one thing nobody can do on your production.

A running environment, not a lab we switch on for a meeting.

29
applications

Every one deployed from Git and continuously reconciled against it.

35
alert rules

Seven of them know what time it is and stay quiet during planned work.

2
repositories

The whole platform and its configuration. Nothing set up by hand.

1
night cycle

A simulated bank day closes and reopens every night on its own.

The traffic in it is generated, not borrowed from a customer — which is exactly why we are allowed to break it. A demo runs against this environment live, not against a recording.

What it is made of

Three layers, one environment

The same three layers we design for clients, wired together the way we would wire them for you. What travels to your environment is the practice, not our pick.

In depth below

Monitoring & observability

Grafana, Prometheus, Loki and OpenTelemetry collectors feeding one set of dashboards, an alert pipeline that ends in the channel the team already reads, and an AI investigation (HolmesGPT) that runs against the same data the moment an alert fires.

See it running →
The change path

GitOps & deployment

Two repositories hold the platform and its configuration. ArgoCD reconciles them into the cluster, corrects anything changed by hand, and secrets arrive from OpenBao rather than living in the repository.

DevOps, CI/CD & GitOps →
Underneath

Kubernetes platform

An RKE2 cluster with hardened defaults, Traefik handling TLS and hostname routing, and cert-manager renewing certificates without anyone remembering to. The platform layer itself is declared in Git like everything else.

Kubernetes & Container Platforms →
How the reference stack is wired Three bands. Declared: Git repositories feed ArgoCD, which reconciles the Kubernetes cluster; secrets come from OpenBao through External Secrets. Observed: metrics and logs leave the cluster through OpenTelemetry collectors into Prometheus and Loki, and Grafana reads both. When something breaks: an alert rule reaches Alertmanager, which notifies the team chat channel directly and in parallel sends the alert to HolmesGPT, whose root-cause analysis lands in the same channel. A note written back into that channel becomes an annotation line on every chart. 01 — Declared in Git Git repositories platform + configuration ArgoCD reconciles, corrects by hand Kubernetes cluster RKE2, Traefik, your applications OpenBao secrets synced in, never in the repo commit and push; a manual change is reverted on next sync metrics and logs leave the cluster 02 — Observed OpenTelemetry collectors node, cluster and app signals Prometheus + Loki metrics and logs, one pipeline Grafana dashboards + alert rules one place to read both, not two tools 03 — When something breaks Alert rule fires 35 rules, 7 aware of the window Alertmanager routing by team label Team chat channel HolmesGPT root cause, evidence, next steps both land in the same channel a note typed back into the channel becomes a line on every chart

Scroll the diagram sideways to see all three bands →

The whole environment in one picture. Nothing in it is installed by hand except the controller that reads the repositories.

Monitoring & observability

Six things this environment shows

Monitoring is the layer with the most to show, so it is the one documented here. Every screen below is from the running environment.

One window, from the business down to the infrastructure

A manager and an operator open the same screen: the state of the business on top, the applications below it, the infrastructure under that, and the monitoring platform checking itself. No second tool holding a second version of the truth — which is where the argument in an incident call usually starts.

Operator dashboard showing business, application and infrastructure rows in a single view
Operator overview in a normal state. The dashboards are in Slovak — an English build is in progress.

A tile has three states, not two

Green and red are the easy ones. The state that matters is the third: the service is up, it is answering, and it is slow. That is what your customer feels first — and it is decided by p95 latency and available replicas, not by eye, so two people reach the same conclusion.

Dashboard tiles showing one application slow, one down and the rest healthy
The same window under load: one application slow, one down, the rest healthy.

An alert that doesn't say who owns it is just noise

Every rule carries a team label that decides the channel and the escalation behind it, and the routing table sits on the same screen. The alert also links to its runbook: one click from "something is red" to "here is what to do about it".

Active incident list beside a routing table mapping team label to channel and escalation
Active incidents on the left; on the right the routing table — team label, channel, escalation.

There are twenty-four of those runbooks, one per rule, all with the same five headings. This is the one behind the alert above, reproduced exactly as it sits in the repository.

runbooks/important-app-down.md critical

Runbook: ImportantAppDown

Condition: 0 available replicas AND bank day ONLINE (conditional alert) · Source: Prometheus + bank-day gate

What's happening

The critical application (apps/important-app) has no available replica while the bank day is ONLINE — a business-impacting outage. The rule is gated: with the bank day OFFLINE the same condition stays silent by design.

Verify
  1. ArgoCD → application important-app — is the Deployment scaled to 0 or failing?
  2. kubectl -n apps get deploy important-app — spec vs available replicas.
  3. Blue "Zmena: important-app" annotation on the dashboards — was there a manual change or a sync right before the alert?
  4. Bank-day tile on Operator Overview — ONLINE means the gate is open and the alert is legitimate.
Act
  • The app is deliberately managed by GitOps with manual sync: open ArgoCD → application important-appSync — this restores replicas: 1 from Git and the pod starts within seconds.
  • Alternative (emergency only): ArgoCD → resource Deployment important-app → Edit → replicas: 1 → Save; reconcile with Git afterwards.
  • Do NOT delete the Deployment — metric expiration would delay alert recovery.
Escalate

App does not start after the sync (pod pending/crashing) → check events (kubectl -n apps describe deploy important-app) and escalate to the app team channel with the ArgoCD sync result.

After resolution

Tile "Kriticka aplikacia" back to OK, RESOLVED in the channel within ~3 minutes. The return is documented automatically — a blue "Deploy: important-app" annotation appears on the dashboards. Record the cause in the ops log.

The runbook behind the alert. Note what it does not say: it does not tell the operator to think — it tells them where to look, what to do, and when to stop and escalate.

Every chart carries the same log of what happened

Two kinds of mark land on the timeline: automatic ones — a deployment reconciled, the bank day switched over — and a note an operator types into the same channel the alerts arrive in. They belong to the moment rather than to one dashboard, so the same line appears on every chart with a time axis. The next morning, the tooltips are the shift handover.

Operations log chart with vertical annotation lines and a tooltip showing an operator note
An operator note written into the alert channel, landing on the operations log as a yellow line.
A different dashboard showing the same vertical annotation lines at the same times
The same marks on a different dashboard — an annotation belongs to the moment, not to the chart it was created on.

A night is a shape, not a list of log lines

Batch processing and the database backup are drawn as bands in time. When throughput drops at one in the morning, it is visibly inside the backup window — the plan, not a fault. The deadline is on the same screen: the close finished at 04:58 against an 05:00 cut-off, and the two-minute margin is not in somebody's head.

Timeline of a bank-day close showing night phases and the margin against the deadline
Bank-day close: the phases of the night, with the database backup marked in cyan between 01:00 and 03:30.

The investigation arrives before you do

When an alert fires, an investigation runs against the same environment — logs, metrics, Kubernetes state — and lands in the same channel: evidence, a root cause with a confidence level, an explicit list of what it could not determine, and the commands to verify it. It is also allowed to disagree: in one run it marked one of our own alert rules as likely stale, and it was substantially right.

AI investigation of a crash-looping pod delivered as a message, with summary, evidence and root cause
An investigation of a crash-looping application, delivered to the alert channel within seconds of the alert.

See the full Monitoring & Observability service →

The fastest way to judge us is to watch our own environment fail.

A live demo runs against the environment above — the dashboards, an alert arriving, an AI investigation, and a service pushed into failure that recovers while you watch. About an hour. No slides.