Live data
How eonelabs.my is built and run
Live data from production, and the pipeline, IAM and cost controls behind it.
eonelabs.my is a one-person project: a FastAPI portfolio plus a handful of side apps, each on its own Cloud Run service. This page shows real, cached numbers from those services and explains the decisions behind them: how a change gets from a branch to production, who is allowed to do what, and what stops a public AI feature from running up a bill. Built and operated by Ikhwan Azmi, Senior Software Engineer (DevOps and AI agents).
Loading live data…
01 · Live
Services, last 24 hours
Each service below is a separate Cloud Run service behind its own *.eonelabs.my domain.
Numbers cover the last 24 hours and come from Cloud Monitoring. Services scale to zero when idle, so a
quiet service can legitimately show no data. p95 latency includes cold starts after an idle period. A
Stale data badge means the last refresh failed and you're seeing
the most recent good data.
02 · Uptime
Uptime checks Stale data
External uptime checks against each public domain, with the 7-day availability and the time of the last check.
03 · Deploys
Recent deploys Stale data
Recent Cloud Build runs triggered by merges to main. Every build runs the test suite before it builds an image, and the image is tagged with the commit SHA, so any live revision traces back to an exact commit.
| Commit | Service | Status | Started | Duration |
|---|---|---|---|---|
| Loading deploys… | ||||
04 · Shipping
Shipping cadence Stale data
Aggregate activity from the GitHub repository over the last 30 days: pull requests merged, the pass rate of CI runs, and when the last merge landed. Every change to production goes through a pull request, even on a solo project, so this is a direct measure of how often it ships.
- Merges to main (30d)
- —
- CI pass rate (30d)
- —
- Last merge
- —
05 · AI guardrails
AI grader status Stale data
The Prompt Engineer Simulator on eonelabs.my has an optional AI Prompt Mode, graded by Gemini through Vertex AI. This panel shows whether it's currently on, how many days remain before it switches itself off, and how much of today's site-wide cap has been used (rounded down to the nearest 10%).
A public endpoint that calls a paid model is an open invitation to a surprise bill. The grader is wrapped in independent layers, so no single failure leaves it unbounded:
- Invite codes. No code, no call. Codes are issued from the admin CMS, can expire or be revoked, and only a keyed hash of each is stored.
- Daily caps. 10 gradings per code, 20 per IP, 50 site-wide. Limits reset daily.
- Auto-off date. Past a configured date the grader stops serving on its own, whether or not anyone remembers to turn it off. An unreadable date counts as expired.
- Kill switch. A single config value turns the feature off with a new Cloud Run revision, no code change.
- Budget backstop. A Cloud Billing budget scoped to Vertex AI only publishes to Pub/Sub. A Cloud Run function, running under a custom role with just two permissions, disables the Vertex AI API if the budget is reached. The rest of the site keeps running; only the grader fails closed. This path has been tested end to end.
The model's input is treated as data, not instructions: the player's text is wrapped in a delimiter with a per-request random nonce, and the output is forced into a JSON schema and validated server-side.
Status
—
Auto-off in
—
Today's global cap used
—
Rounded down to the nearest 10%. No per-code, per-IP or raw request counts are published.
06 · Architecture
How a request reaches a service
DNS for eonelabs.my is hosted at Exabytes. Each project gets its own <name>.eonelabs.my
subdomain, pointed via CNAME at Google and mapped straight to its Cloud Run service with a Cloud Run domain
mapping. That gives every app its own clean URL without a global load balancer, which would have added a
fixed monthly cost to a site that otherwise costs close to nothing at rest. The portfolio reads and writes
Neon Postgres, gets its secrets from Secret Manager, and calls Vertex AI with its own service identity
instead of an API key. Cloud Monitoring collects the metrics this page displays.
07 · Delivery
How changes ship
There's no staging environment. The safety net is a reviewed pull request and a pipeline that refuses to deploy untested code.
-
Branch + pull request
Every non-trivial change starts on its own branch. The pull request opens a reviewable diff and a clean rollback point.
-
GitHub Actions
pytestruns on every PR, plus a Tailwind drift check that fails if the committed CSS doesn't match the templates. Actions are pinned to commit SHAs. -
Review, then merge to
mainThe diff is read before anything merges.
mainis the only branch that can reach production. -
Cloud Build to Cloud Run
Runs the tests again, builds the image, tags it with the commit SHA and deploys the portfolio. Side apps compare the git tree hash of their directory with the hash recorded on their live service and only redeploy when it changed. A new revision goes live a few minutes after the merge.
-
Rollback
Old revisions stay available, so a rollback is shifting traffic back to a known-good revision. No revert commit or rebuild needed. Database migrations are separate, manual and reviewed, and written so the previous revision still works against the new schema.
Why tree hashes? Cloud Build checks out a shallow clone where HEAD~1 isn't reliably available,
so a "what changed" diff kept falling back to deploy-everything. git rev-parse HEAD:<path>
needs no history at all.
08 · Workflow
One person, eight scoped AI agents
Day-to-day work on this repo is done with Claude Code, set up as an orchestrator that routes each change to one of eight scoped subagents: backend, frontend, content/SEO, QA, DevOps, security, docs and mobile. A change that spans several lanes is split up and integrated by the orchestrator, not handed wholesale to one agent.
Merges to main, production database actions and manual cloud commands stop at an explicit
approval gate that only a human can clear.
09 · Cost
Designed to cost close to nothing at rest
Nothing here runs unless someone is using it. Costs are capped by design, not by watching a dashboard.
-
Scale to zero
Services run with no minimum instances and a small, fixed maximum instance count.
-
No load balancer
Subdomains use Cloud Run domain mappings, which have no recurring charge.
-
Serverless Postgres
The database is Neon, not an always-on instance.
-
Bounded AI spend
Invite codes, daily caps, an auto-off date, a kill switch, and a Vertex AI-only budget that disables the API if it's reached (see AI guardrails above).
-
No per-visitor API calls
This page serves one shared, cached snapshot. See how this page works below.
10 · Security
Security posture
-
Secrets in Secret Manager
Mounted per secret, never committed to the repo.
-
Least-privilege runtime identities
Services deployed by the pipeline run as their own service accounts instead of the default compute account, with per-secret (not project-wide) secret access. Side apps that call no Google APIs get an identity with no roles at all.
-
Read-only identity for this page
It can read metrics and build history and one read-only GitHub token. Nothing else: no database, no other secrets.
-
Keyless AI access
Vertex AI is called with the service's own identity, not an API key.
-
Origin check on admin writes
Every state-changing admin request must come from the site's own origin, which also blocks other
*.eonelabs.mysubdomains from riding the admin session. -
Hardened admin session
Password compared in constant time; session cookie is Secure, SameSite=Lax and expires after 8 hours.
-
Pinned supply chain
The base image is pinned by digest and GitHub Actions by commit SHA. Dependabot proposes updates for pip, Docker, npm and Actions.
-
Unprivileged container
The app runs as a non-root user.
-
Manual, reviewed migrations
No schema change reaches production Neon without a tested script and an explicit go-ahead.
11 · Under the hood
How this page works
This page is its own small Cloud Run service. It never calls Google Cloud or GitHub on your behalf. Each instance keeps one snapshot of the data and refreshes it server-side at most every 10 minutes; every visitor in between gets the same cached copy.
If one source fails, the rest of the page still loads and that section is marked Stale data instead of erroring.
It runs under a read-only service account, and it deliberately leaves out anything that would help an attacker: no internal URLs, account identifiers, revision names, branch names or commit messages. Only short commit SHAs.