back to the home page

Vianova

Five years of APIs, data and AI for cities and mobility operators

Vianova collects mobility data from shared-mobility operators and other partners, then gives operators and cities, in places like Munich, Dublin, Malmö and West Sussex, dashboards, maps, reports and an API to explore it. I joined in 2021. Today I'm Lead Backend Engineer, and I'm the largest contributor to its backend. Here is what that means.

5 yearssince 2021
~80%of Query API commits
23×fewer rows on a year-long query
6automations every weekday

The query API

what the dashboards run on

Customers ask for their data as typed JSON, and the API compiles it to Snowflake SQL. A colleague wrote the first endpoint. I built the query language on top of it, and I've been its main developer ever since.

  • Filters, aggregations, computed fields, joins, pivots, custom metrics and geospatial operations
  • Raw points snapped onto roads, areas or H3 cells
  • Customer files turned into queryable, map-ready datasets, with dashboards created automatically
  • About 80% of the commits on this code, and 83% of the lines still there today

AI in the product

ask a question, get a chart

Since September 2024, you can type a question in plain language. Claude writes the query, the API validates it, and it can become a chart. I built this from the first commit, and I still maintain it.

  • Tested like code: CI fails if query generation drops below 85%, or suggested prompts below 90%
  • Explanations of a generated query, and suggested prompts for each dataset
  • One interface over Anthropic, Bedrock and OpenAI, now behind nine use cases
  • PowerPoint reports built from a dashboard, with AI-written analysis in several languages, from prototype to production in five months
  • AI dataset categorization, from hackathon idea to default on upload in a month

When production pushes back

the fixes worth telling

Real clients and real data find what tests don't. These are the ones I'm happiest about.

  • Year-long queries didn't fit the 29-second API timeout. Routing them to a daily rollup cut about 40M rows to about 1.7M, with no change for callers
  • One slow client could freeze the API for everyone. I traced it to cached routes blocking the event loop, fixed it, and added request deadlines and query cancellation
  • A live traffic-data pipeline ran on a colleague's laptop. I moved it to scheduled cloud jobs with alerts, five weeks before a vendor deadline
  • Pydantic v1 to v2 across the backend in about four weeks: 217 files, with the API contract unchanged

Data

dbt on Snowflake

The data reaches the API through a dbt project of 483 models, and I've been its top committer since 2022.

  • Brought unit testing to the project in 2022, and wrote about 42% of today's unit tests
  • Rebuilt regulation compliance history so each hour belongs to the rule version in force, checked against 176,000 production version pairs
  • Built the first dbt pipeline into the stream serving table, then made it safe: partial data can't overwrite full days, and empty merges fail loudly
  • Automated 30-day deletion of citizen report photos and comments, backups included, with a test that fails if anything is left

How I work now

from a Slack message to production

Six automations run every weekday, in Paradev. They triage new tickets, start a Claude Code session in its own worktree for each ticket I label, check what shipped, and draft my stand-up. The thinking stays with me. By my estimate, agents now write over 80% of my code.

A small, clear fix

Slack message or alerttriage investigatesI pick the routethe agent fixes itI review the diffMR, CI, review, deployI read the closing noteQA sweep checks prodI close it

Something that needs thinking

ticket labelledsession opensagent grills meI answer every roundspecI confirm the test seamsslicesI approve the breakdown3 builders in parallel, test-firstMR, CI, review, deploy

Agents propose, I apply

Triage can read and comment. It has no permission to change a ticket.

Safe to run twice

A stopped ship step checks the live state, then resumes where it stopped.

Parallel, with a cap

Three builders at once. More just thrashes the laptop.

The plan-to-build chain is adapted from Matt Pocock's skills. The automations around it are mine.

Under it

  • Python
  • FastAPI
  • Snowflake
  • dbt
  • PostgreSQL
  • Redis
  • AWS Lambda
  • App Runner
  • Cognito
  • Pulumi
  • GitLab CI
  • Streamlit
  • Claude
  • Claude Code
  • Paradev

Want this on your team?

write me