Automation & Tooling

Job-search platform

A self-hosted application I built and operate on the same platform that runs everything else - a real app with a real data pipeline, held to the same review and migration discipline as the infrastructure.

What it is & why I use it

The job-search platform is a self-hosted application I built to run on top of AutomationLab. It matters here because it is the proof that the lab is a platform, not just infrastructure for its own sake: a real app, with a database and a scheduled data pipeline, deployed and operated with the same GitOps and pipeline discipline as every other workload.

Building it end to end - schema, data collection, deployment - is also where a lot of the platform's rougher edges showed up first, because an application with persistent state exercises parts of the system that stateless services never touch.

How I use it in the lab

  • Deployed like everything else. The app ships through the same build-and-deploy path as the rest of the cluster - reviewed changes, versioned images, reconciled state - not a hand-deployed pet.
  • A scheduled data pipeline. Staged jobs collect and enrich data on a schedule, so the app's content stays current without manual intervention.
  • Database-backed with real migrations. Schema changes are version-controlled migrations that apply as an explicit pipeline stage - which turned out to be the single most important operational detail (see the gotcha).
  • Secrets from the manager, config from git. Connection details come from the secrets manager at run time; everything non-secret is declared in the repo.

Architecture

Diagram coming App + database + scheduled collect/enrich pipeline, with the migrate step gating schema changes. Scrubbed of hostnames, connection strings, and addresses.

In action

Screenshot coming The pipeline run showing the migrate stage applying a schema change before the app picks it up. Captured per the publishing checklist - hostnames, connection details, and any data redacted.

Lessons learned & gotchas

Gotcha - a merged migration is not an applied migration The one that cost me real confusion: merging a PR that adds a database migration does not change the schema. The migration only takes effect when the pipeline's migrate stage actually runs - here, as part of the scheduled data pipeline. So right after a merge, the code expects a column the live database does not have yet, and you get errors that look like a bug in the app when the real cause is "the schema change has not been applied." The rule I now follow: never assume a merged migration is live - run the migrate stage (or verify against the database) before trusting it.
  • Deploy order matters for stateful apps. Code that depends on a new column has to land after the migration that adds it, not merely after the migration is merged. "Merged" and "applied" are different points in time, and the gap is where outages live.
  • Verify schema against the database, not the repo. The repo tells you what the schema should be; only the database tells you what it is. When something looks broken after a change, check the actual schema first.
  • An app with state is the honest test of a platform. Stateless services hide a lot of sins. A real database, real migrations, and a real schedule are what proved the platform could carry production-shaped workloads, not just demos.

Impact

1 app
built and operated end to end
Scheduled
collect + enrich pipeline
Gated
schema migrations

The job-search platform is the workload that turns AutomationLab from "infrastructure I automated" into "a platform that runs a real application." The migration lesson is the one I carry everywhere now: shipping the code is not the same as changing the world it runs in, and the discipline is verifying the change actually landed - not assuming a merge made it so.

Code & further reading

The application and its pipeline are scrubbed of hostnames, connection strings, credentials, and any personal data before anything is published.