Available Hire Me
← All Writing Data

Shipping a Daily Report Pipeline — from Data to Self-Contained HTML Archives

How a daily report pipeline produces self-contained HTML archives — deterministic naming, zero-dependency files, auto-discovery, and a browsable timeline.

A daily report is only useful if it reliably appears, is shareable, and stays reviewable months later. The naive approach — a server that renders a page on demand — fails all three in different ways: the page is only as alive as the server, the link breaks when the deployment changes, and last month’s report is a database query away rather than a file you can point someone at. This post is the pipeline that produces the UK Gilt Daily Report: a scheduled job that turns market data into a single self-contained HTML file, named so the archive builds itself. Every design decision below exists because of one requirement — the artifact must outlive the pipeline that made it.

The pipeline shape

The pipeline is a batch job, not a service:

fetch → compute → render → publish
  • fetch — pull the DMO universe and the day’s market data. Fail here and the job stops early with a loud error; a report built from partial data is worse than no report.
  • compute — price every instrument: clean/dirty, accrued interest, gross and post-tax yields across the tax bands, curve and OIS spreads, duration, DV01, holding-period returns. A calculation version is stamped into the output, so “which engine built this report” is a property of the file itself.
  • render — produce the report as HTML.
  • publish — drop the file into a known folder. That is the entire deployment story.

A batch shape matters because reports are the same every day — there is no request-time computation to justify a server. The job runs on a schedule, writes one file, and exits. The scheduled tasks post is the layer that makes the schedule trustworthy — cron timezone pinned, failures alertable, no overlapping runs.

The artifact is a file, not a page

The report is generated as one self-contained HTML file. No server-side template, no database lookups at read time, no external CSS or JS beyond a pinned, hash-verified Chart.js from a CDN. Three consequences fall out:

  • The numbers are baked in. Nothing is computed in the reader’s browser, so the file is a permanent snapshot of what the engine believed on that date — not a live recomputation that could differ later.
  • It can be sent anywhere. Email it, link it, file it. The file does not depend on the pipeline’s lifetime.
  • It is auditable. The rendered HTML is the output; there is no layer between what was generated and what was reviewed.

The trade-off worth naming: self-contained HTML files are bigger than pages — the sample is over a megabyte because it carries everything inline. That is the price of portability, and for a daily report it is trivial.

Deterministic naming is the archive’s contract

The filename is the file’s metadata, and it is load-bearing:

gilt-report-2026-08-19.html

Three rules make the archive work:

  • The date in the name is the report date, not the generation date. A report about 19 August generated on 25 August must be named for 19 August. Generation time lives inside the file; the name says what the file is about.
  • The pattern is fixed. gilt-report-YYYY-MM-DD.html — sortable lexically, parseable trivially, and matching a glob. The archive page and every future consumer derive all metadata from the pattern.
  • No front matter, no YAML. The file is a static artifact, copied byte-for-byte and never processed. That keeps the report free of Liquid or templating hazards and keeps the pipeline’s output honest.

Auto-discovery: the archive builds itself

Because the naming is deterministic, the archive needs no registry. The listing page enumerates the folder at build time — glob for gilt-report-*.html, sort by name descending, and everything displayed (the date label, the day of week, the “Latest” badge, the report count) is derived from the filename. Publishing a report is a file copy: rename, drop in, done. No database row, no config edit, no risk of the registry and the folder drifting apart.

The same discipline applies to malformed files: anything not matching the pattern is ignored, and an unparseable date is rejected rather than rendered as a plausible-looking wrong date. The archive’s correctness comes from the filename being a contract, not a hint.

The archive as a development log

The reports do double duty. Each file is a snapshot of the market on that date — and equally a snapshot of the engine on that date: its calculation version, its layout, its feature set. Keeping every report means the evolution of the tool is visible side by side, and a piece of feedback can reference a stable link to the exact version it was about. “It was different on the 19th” is answered by opening the 19th. That property — older versions stay reachable and comparable — is what turns a daily job into a timeline, and it falls out of the naming rule for free.

Why static wins for this job

Every alternative has a hidden cost. A database-backed page needs the database and the server alive forever, and “what did the report look like in June” is a migration away. A PDF is shareable but not inspectable — you cannot click a row and expand a bond’s detail. Self-contained HTML is the intersection: permanent, portable, interactive, and openable by anyone with a browser. For a report that must be both correct and provable, the artifact being a plain file is the feature.

The pipeline is deliberately small — a scheduler, a batch job, a naming convention, and a folder that enumerates itself. Each piece is replaceable, and the whole thing degrades gracefully: if the job fails, yesterday’s file is still there, still correct, still linkable. That is the property you actually want from a daily report pipeline — not a dashboard, but an archive that never lies about its history.

The /gilt-reports/ archive is the pipeline in production — a single sample report so far, with the naming and discovery already doing the work. If you’re building a daily report pipeline and want the artifact and archive design right the first time, reach out.

Samuel Jackson

Samuel Jackson

Senior Java Back End Developer & Contractor

Senior Java Back End Developer — Betfair Exchange API specialist, Spring Boot, AWS, and event-driven architecture. 25+ years delivering high-performance systems across betting, finance, energy, retail, and government. Available for Java contracting.