Harish Darko

Backend, Cloud and Reliability Engineerabout 2.5 years of Java and Spring Boot in fintechOntario, Canadaopen to backend and reliability roles

JavaSpring BootSQL / PostgreSQLAWSTerraformDockerCI/CDReactLLM evaluation

From my article, From Code to Intent, July 6, 2026

“Fast isn't the same as correct.”

I wrote that AI moves our job to intent plus verification: knowing what the software must do, and proving that it does. Since then I've tested it on my own builds, with the mistakes left in.

the agent builds someone catches it a test pins it the test passes next build where the rule breaks (every build, so far) 01Intentwhat must be true 02First draftwhere it went wrong 03Caught bywho saw it, and how 04Fixthe real line that changed 05Proofwhat shows it worked

Click a state to read it, or pick a build to change the example.

Three builds, five layers

Pick a build, then step through its five layers. The mistake is always in layer 2, and a different kind of check caught it each time.

July 2026

CaseLens

AI ticket triage that shows its reasons, with a person able to override every call.

Built withJava 21, Spring Boot, PostgreSQL, React 19, AWS (API Gateway, Lambda, SQS, EventBridge, S3, CloudFront), Terraform, GitHub Actions

114 backend tests12 frontend tests2 browser journeyslive on AWS, ca-central-1

relay the database zzZ compute the schedule

A run every minute never gives the database its 5 idle minutes, so it never sleeps.

September 2026

OwnVera

Portfolio intelligence for ETF investors: what you really own, traced to the source.

Built withJava 25, Spring Boot 4.1, Spring Modulith, PostgreSQL 17, Flyway, React 19, TypeScript, Testcontainers, Playwright, axe, Docker

app starts warmup, about 15 s positions import, still writing empty view 0 priced positions snapshot store stored discarded, not stored read: “no priced positions” read: the real look-through

Full test suite: overlap expected 1, got 0. The empty view is stored, so every later read shows “no priced positions”.

November 2026 · my AI-coding workflow

Promise Review

A builder agent writes code from my spec. A fresh reviewer tries to break every promise.

Built withClaude Code and Codex agents, Markdown specs, pytest, seeded property tests, deliberate-break checks

Round 1 findings 4 blocking Equal huge distances (1e308)overflow to infinity blocksout of range Opposite huge distancesoverflow the turn blocksout of range No test fails if thelength check is removed blocksout of range No test fails if thestring check is removed blocksout of range
spec: input:

4 blocking findings. Without ranges, impossible inputs count as bugs.

Choose a layer

Pick a layer:

  1. for: a support team with no overnight cover, while tickets pile up

    Triage tickets in seconds, show the exact words behind each call, and let a person override it. Cost almost nothing while idle.

  2. The outbox relay ran every minute. I asked why. Then I let it stand.

    # infra/terraform/main.tf
    schedule_expression = "rate(1 minute)"
  3. caught by: me, two weeks late

    The free database compute ran out. With a run every minute, the database never got 5 idle minutes to sleep.

    Then, in October, an agent reading the code: the pool kept idle connections and renewed them every 30 minutes, and a cleanup job ran every hour. Each one woke the database.

  4. # July: main.tf
    - schedule_expression = "rate(1 minute)"
    + schedule_expression = "rate(30 minutes)"
    # October: application.yml (abridged)
    + minimum-idle: 0
    - fixed-delay-ms: 3600000   # 1 hour
    + fixed-delay-ms: 21600000  # 6 hours
  5. A Terraform test asserts the schedule. CI doesn't run that test yet. I'm watching the compute numbers to confirm the October fix.

    # tests/relay_schedule.tftest.hcl
    condition = ...schedule_expression
             == "rate(30 minutes)"

    What I learned: when I ask why, I get the answer before I move on.

  1. for: self-directed ETF investors who want to know what they really own

    Look through every ETF to the companies, countries and sectors inside, and trace every number back to a row you imported.

    My rule: Java owns the numbers. The AI only phrases facts the engine has already verified. It never calculates.

  2. The look-through takes about 15 seconds cold. So a warmup job computed it at start-up, and saved whatever it got.

    # XRayViewStore.java (simplified)
    snapshots.save(view);
    #   even when view has no priced positions
  3. caught by: the full test suite, but only when all of it ran

    overlap expected 1, got 0.

    The agent first called it "pre-existing, unrelated to this change". It stayed on the list. Three days later the cause was the warmup: if it ran while data was still being written, it saved an empty view, and every later read served it.

  4. # commit 653eb99 (abridged)
    + if (view.positions().isEmpty()) {
    +     snapshots.deleteById(portfolioId);
    +     return;
    + }
    # and in tests:
    + ownvera.xray.warmup.enabled=false
  5. The suite-only failure is gone, and the commit names it as the root cause. Across the app, the AI evaluation shows 24 of 24 required tool routes and 0 ungrounded numeric claims, and axe accessibility checks are clean on 7 routes in both themes.

    Still open: a dedicated regression test for the store itself. It's on my list.

    What I learned: a test that fails only in the full suite is a bug report, not noise.

  1. for: anyone shipping code an AI wrote

    Write the promises first. A reviewer that never saw the build tries to break each one, and may only block on what it can prove against the spec. No generic "hardening".

  2. My spec for a robot's odometry maths said "always", with no input range.

    | P1 | Equal left and right distances
    |    | give a turn of exactly 0  | always |
    #    no range: so any number counts
  3. caught by: a fresh reviewer, round 1

    2 of its 4 findings needed wheel distances near 10308. No robot can produce that, but the spec promised "always".

    Then my question: I asked whether the fix was specific to robotics. Answering it, the agent found its new rule would also excuse attacker-sized input to a web API.

  4. # SPEC-TEMPLATE.md (abridged)
    + Input ranges: every number gets a
    +   realistic range and a rule outside it.
    + Mark each input trusted or untrusted.
    +   Untrusted: anything an attacker
    +   can send. No exemption.
  5. The maths ended with 90 passing tests, 7 written by the reviewer, and every high-risk promise broken on purpose to check that a test catches it.

    In a small comparison (one run each, a signal, not proof), this workflow scored 17.5/20 on blind probes, against 12.5 for the same model working alone.

    What I learned: a vague promise wastes the reviewer's time on the wrong bugs.

Experience and education

Fintech taught me to care about correctness, traceability and what happens after deployment. Then I studied cloud in Canada, and built the projects above.

Experience

  1. 2026 to now

    Independent builds · Ontario

    CaseLens on AWS, OwnVera and Promise Review, each verified and logged on this page.

  2. Apr 2023 to Oct 2023

    Software Engineer, Backend / Platform · Ionixx Technologies, fintech SaaS

    Java and Spring Boot services and REST APIs. Standardized GitHub Actions workflows for build, test, Docker packaging and post-deployment smoke checks. Investigated production issues on AWS through logs, metrics and recent release changes.

  3. May 2021 to Apr 2023

    Junior Software Engineer, Backend / Platform · Ionixx Technologies

    Java and Spring Boot code, REST APIs and SQL. Built Jenkins pipelines with build, test, deploy and smoke-test stages. Troubleshot build failures, API errors and database connectivity with developers and QA.

Education

  1. Postgraduate Certificate, Cloud Computing · Durham College

    2024 to 2025 · Honor Roll

  2. Postgraduate Certificate, Information Technology · Conestoga College

    2024 · Distinction

  3. Bachelor of Engineering, Computer Science · KCG College of Technology

    2017 to 2021 · First Class

Ask me to walk you through

  1. How an API change moves from code to build, container image, deployment, health check, logs and runbook.
  2. How Terraform keeps a cloud change readable before anyone applies it.
  3. How logs, metrics, request IDs and smoke tests narrow down a production issue.
  4. How I use AI to research and build, then check its output with source review, tests and runtime checks.

Verification log

Every mistake I've caught and proven fixed, newest first. No single check caught everything, so I stack them: tests, a fresh reviewer, my own eyes, and asking why.

  1. 2026-11-06Promise Review

    A new reviewer rule would have excused attacker-sized input

    Caught by: my question, "is this fix general?"

    Fix: every spec input is now marked trusted or untrusted; untrusted input gets no exemption.

  2. 2026-11-05Promise Review

    Specs with no input range made impossible inputs count as bugs

    Caught by: a fresh reviewer that only saw the spec

    2 of 4 round-1 findings needed wheel distances near 1e308. Fix: the spec template now asks for a realistic range for every number.

  3. 2026-11-05Field robot

    Wheels slide when a skid-steer robot turns, so a square looked like a triangle

    Caught by: the simulator's ground truth

    Fix: effective track width 1.02 m from a spin test. Error after a 16 m lap: 4.06 m before, 0.044 m after.

    See the real paths

    Off by 4.06 m after a 16 m lap with the real 0.76 m track, and by 0.044 m with the calibrated 1.02 m. Real simulation data, not a drawing.

  4. 2026-10Support Desk

    Transaction IDs were only unique per station, so one station overwrote another

    Caught by: a second model I asked to review it, in two rounds

    Fix: the key is (station_id, transaction_id). Proof: CI runs the regression test with the fix switched off, and the build fails if that test still passes.

  5. 2026-10Support Desk

    Events were sorted by the device's own clock, which a clock correction can flip

    Caught by: the same review

    Fix: replay events by sequence number, and send any gap in the sequence to a person.

  6. 2026-10CaseLens

    Idle pool connections and an hourly cleanup kept waking the database

    Caught by: an agent reading the code

    Fix: minimum-idle: 0, cleanup every 6 hours. Proof still open: I'm watching the compute numbers.

  7. 2026-09-24OwnVera

    A warmup job saved an empty look-through, and every read served it

    Caught by: the full test suite, only when all of it ran

    Fix: commit 653eb99, empty views are never stored. Still open: a dedicated regression test for the store.

  8. 2026-09-23OwnVera

    Every news search failed, and the page kept showing a stale brief

    Caught by: an AI review I asked for, which saw "Sources (1)" with no sources

    Cause: the search schema had 11 properties and the limit is 10. Fix: ed3617d. Proof: an end-to-end test for honest quiet, stale and unavailable states.

  9. 2026-09-21OwnVera

    Save didn't work in the read-only demo, and a chart line had no legend

    Caught by: me, on my phone

    Fix: demo saves go to browser storage (2bc65a3), both legend styles shown (8bd081b), each with its own test.

  10. 2026-07CaseLens

    A relay running every minute never let the database sleep

    Caught by: me, two weeks late, when the free compute ran out

    Fix: rate(30 minutes), asserted by a Terraform test. CI doesn't run that test yet.

What I do that the AI doesn't

So how do I use AI? It writes most of the code. I decide who it's for and what it must never do. These parts stay with me.

  1. Check its work, and check my checking

    I gave the same tasks to different setups, all with the same builder model, and scored them without knowing which was which. All passed the 79 hidden tests. Only my break-it tests showed the difference.

    1. Builder alone12.5
    2. With a fresh reviewer16.5
    3. A three-agent team18.5
    4. Test-first builder, reviewer that proves each break19

    Blind scores out of 20, Nov 1 and 2. The key stayed in a separate file. I can show the method and results.

  2. Notice what a user feels

    When I had to scroll to see what my click did, I told the agent:

    “Understand the pattern and fix the root cause.”Oct 24

    It became a rule, then an automated check at five screen sizes.

  3. Run my agents as one team

    One shared memory under my written rules, a notebook where every agent logs what it tried and what failed, and checks built from their past mistakes. I set it up and I run it.

What my agents must never do

In my article I said intent includes what a system must never do. For my own agents, I write that down before they start. Flip a sign to see what happens instead.

Six signs. Each is a rule I wrote down for my agents after something real.

More work and writing

Support Desk follows the same five layers, and two of its catches are in the log. The advisor and the lab show research and operations work. The articles go deeper on the same ideas.

What I'm sharpening now

I own the outcome on my builds. Here's what I'm sharpening now.

fundamentals my own code system design

Tap a signpost.

  1. Fundamentals, by name

    weekly

    CAP, isolation levels, concurrency. For each one: a definition, an example from my own code, and the trade-off.

  2. Explaining my code without notes

    practising

    Code maps of Support Desk and CaseLens are done. Now I trace a request end to end, timed.

  3. System design, 10-week plan

    week 1 of 10

    Twelve lessons and eleven case studies in a study site I built. I draw each system from memory, then defend it in a mock interview.

I learn fastest next to people who know these deeply, and I bring the habit of proving what I build.

Give me a rough idea.

I'll research it, build a working prototype, check it, and come back with a proposal. I'm open to backend, cloud and reliability roles in Canada.