Adapters before abstractions
Heterogeneous sources remain isolated in city connectors; the rest of the system works with one common representation.
Personal engineering product · live in production
I turned a fragmented parking search into findparking.ch: a public product that combines live availability, historical context and short-term forecasts across several Swiss cities. I designed, built, deployed and continue to operate the complete system.
01 — Genesis
When I drove to Zurich, checking parking availability was unnecessarily fragmented. The information existed, but comparing several relevant facilities meant opening separate sources one by one.
The first product idea was deliberately simple: show multiple parking facilities together so a driver can compare current availability immediately.
A second question appeared early. If I leave in 30–60 minutes, the current number is not enough: is a facility likely to become fuller or emptier? Answering that required something the source sites did not provide—a usable history.
02 — Product evolution
The first public version was primarily a set of availability tables. It solved the comparison problem and started collecting observations without waiting for a sophisticated interface.
Scheduled snapshots turned temporary public values into time series. The current production history reaches back approximately to September 2025.
Zurich provided the first development and test case for short-term prediction, followed by systematic comparison of several approaches.
Once the shared pipeline existed, new cities could reuse storage, evaluation and presentation while adding only a source-specific ingestion adapter.
The table MVP has evolved into a polished, responsive public interface with comparable cards and an interactive map.
The sequence matters: the product was already useful while the data asset and the more experimental capabilities were still developing.
03 — Architecture
Swiss cities and operators expose parking data through heterogeneous formats and endpoints, including XML and JSON. There is no single standard Swiss parking API behind the product.
Each city therefore has its own retrieval and adaptation connector. After normalization into a common internal representation, the PostgreSQL storage, forecasting and evaluation logic, Flask application and user interface are shared.
04 — Data pipeline
A city connector calls its public source and handles that source’s particular format.
City-specific fields and statuses are translated into the shared internal shape.
Usable observations are persisted as timestamped PostgreSQL snapshots instead of overwriting the previous state.
Scheduled jobs produce short-term estimates from the accumulated history when enough fresh data is available.
Forecasts are compared with later observed availability and model error is tracked, including with MAE.
Flask serves the public cards and map, while private health views expose freshness, job status and detected problems.
Conventional cron is sufficient at this scale: ingestion runs approximately every 5 minutes, prediction jobs every 15 minutes, and backups daily. The different cadences avoid recomputing forecasts every time a raw observation arrives.
05 — Product and engineering decisions
Heterogeneous sources remain isolated in city connectors; the rest of the system works with one common representation.
Collecting snapshots early created the evidence needed for later forecasting instead of forcing a prediction feature onto insufficient data.
Different schedules are explicit and easy to operate on one modest server. More infrastructure would not yet create proportional value.
Monitoring distinguishes application failures from stale, missing or changed upstream data. Repairs still require diagnosis and, when necessary, connector changes.
06 — Historical data
Production observations currently reach back approximately to September 2025. No row count, database size or query-performance claim is published because those values are not verified here.
Each retained update makes availability an observable time series rather than a disposable number. PostgreSQL on the VPS supports the live application, historical comparisons and the prediction/evaluation pipeline.
The value compounds gradually. A new city can join the common forecasting framework only after a compatible public source is ingested and enough history has accumulated; the architecture cannot compensate for data that an operator does not publish.
Current availability
Current availability
+ One-hour comparison
+ Historical observations
+ Short-term estimates
+ Forecast evaluation
07 — Forecasting experiments
The current system is in an experimentation and evaluation phase, not a finished machine-learning platform. Approximately eight forecasting approaches are being compared rather than presenting one model as definitively best.
Predictions are stored and later compared with the availability that was actually observed. The private operational dashboard tracks model performance using measures including Mean Absolute Error (MAE), making selection evidence-based.
The public interface currently exposes estimates one and three hours ahead when fresh data, capacity and a current model are available. It labels them as estimates—not guarantees—and withholds them when the inputs are insufficient.
08 — Current public product
Users can scan responsive parking cards or switch to a geographic map. Cards show the current free spaces and known capacity, a colour-coded availability state, the change and availability around one hour earlier, data freshness and—when valid—short-term estimates.
The map uses Leaflet with OpenStreetMap and presents the same core availability context geographically. The current experience is a substantial evolution from the original table MVP, while remaining focused on the practical comparison task.
Browse current parking availability and short-term estimates across the supported Swiss cities.
Visit findparking.ch ↗09 — Production operations
A password-protected internal health dashboard covers ingestion status, data freshness, prediction jobs, detected issues and MAE-based model comparisons. Authentication protects this operational view; it is not a consumer account system.
Real scheduled-job failures and upstream data problems motivated the monitoring and alerting. Some incidents originate in the application; others occur when an operator stops publishing, serves stale or unusable data, or changes its source. The pragmatic response is to detect, diagnose and adapt—not to claim perfect uptime or automatic repair.
10 — Continuous improvement
Development continues both to polish the actual product and to create a realistic environment for technical experimentation.
A full consumer account ecosystem, extensive notifications, payments and commercial infrastructure remain intentionally outside the current product.
Azure and Snowflake are being explored and prototyped for practical learning; they are not presented as critical production dependencies.
A modest VPS and cron jobs create enough operational responsibility to learn from failures without building infrastructure the product does not need.
11 — Current state
The achievement is the lifecycle, not commercial traction: idea, table MVP, continuous data collection, forecasting experiments, responsive UI, production deployment, monitoring, maintenance and roadmap all belong to one coherent product.
The site is public, but user acquisition is not currently an objective. I am the primary regular user, with occasional use by friends and others who have received the link; no meaningful MAU, DAU or traffic claim is available.
12 — End-to-end ownership
I identified the problem, scoped and shipped the first useful version, designed the connector boundary and PostgreSQL history, built the Flask application and responsive interface, introduced forecasting evaluation, and deployed the product on a Linux VPS.
I also operate it: scheduling jobs, maintaining backups, monitoring freshness and model performance, responding to application and upstream-source failures, and deciding which improvement is valuable enough to add next.
Positioning: this is a personal engineering and product project built outside my employment. There is no client, corporate stakeholder process, team-leadership claim or commercial traction story behind it. Its value is direct evidence that I can take a technical product from a personal problem through production operation and continuous improvement.
13 — Long-term roadmap
Parking availability is a mobile, real-time use case. A native application is a future direction rather than a committed delivery or a feature already under development.
Accounts and favourite facilities could support persistent views centred on the parkings a person actually uses.
Selected-facility monitoring could make changes more actionable without turning every update into noise.
A phone-first application could make the comparison faster before and during a journey.
Payments or other commercial capabilities would be considered only if the product genuinely evolves in that direction.