Household Energy Forecast
Links
Why Energy Data
During my first year in Zambia with the Peace Corps, I lived with no electricity at all. A few times a week I'd ride a bike into the boma just to charge my phone, or find power wherever I could. In my second year, I got some village boys to help me climb up onto my thatch roof and install a solar panel I'd bought in town, wired it up to an inverter and a car battery inside my hut, and used that setup for the rest of my time there.
That experience got me genuinely into solar and electricity usage. I was constantly checking my battery levels and watching the weather, trying to figure out how much power I'd have to work with. That habit never really went away. These days I've got a whole-home energy monitor, a smart thermostat, and a handful of 433 MHz temperature and humidity sensors scattered around the house, and I still find myself digging through the data trying to spot gaps and patterns in how we actually use energy day to day. Building a machine learning model to predict and understand household energy use is squarely in my wheelhouse, and it's a good excuse to get more comfortable with Snowflake along the way.
Everything here is public: the code, the process, and an open dataset of household electricity usage. There's no proprietary or sensitive data involved.
I've used spec-driven development before, OpenSpec at work and GitHub's spec-kit on personal projects, and it's become my default way of working with an AI coding agent. Each stage starts with a written spec and plan that I work through before implementing anything. It's a bit slower up front, but it keeps the reasoning visible and the work honest. You can follow the "why" in the repo, not just the "what."
Decisions so far
- Data source: the UCI "Individual Household Electric Power Consumption" dataset. It's one household, with minute-level readings over about four years.
- Goal: forecast next-day total household electricity consumption, checked against a simple baseline so the model actually has to earn its keep.
- Storage: Snowflake is the system of record for raw and processed data, not a pile of local CSVs.
- Compute: I'm keeping this local plus GitHub Actions for now, with no GCP or other cloud platform. I don't want to take on cloud infra cost and complexity before the core pipeline even works. I might revisit that as a later phase.
I wrote all of this into a project constitution before touching any code, so these constraints (public repo, no secrets, open data only, spec-driven, Snowflake-first, local-first) are checked against every later spec instead of getting quietly forgotten.
Building It Out
With the spec, plan, and task breakdown written, I moved into actual implementation: a Python package with a Typer CLI, one command per pipeline stage (ingest, aggregate, train, forecast, run-all), config handling that reads Snowflake credentials from environment variables only, and the first real slice of the pipeline working end-to-end, downloading the UCI dataset and loading it into Snowflake idempotently, then aggregating it into daily totals.
Along the way I set up an actual Snowflake trial account to test against, rather than just writing code against an imagined schema. I went with the Snowsight web UI instead of the Snowflake CLI this time, mostly to get a feel for where things live. The autocomplete on queries turned out to be genuinely useful for a first-timer. I ran into a few race conditions running multi-statement SQL files (a CREATE VIEW referencing a table that hadn't finished being created yet), which just meant running statements one at a time until the schema was fully built out.
Personal user credentials aren't meant for machine-to-machine auth, that's standard practice, not a workaround. Key-pair authentication was the plan from the start: an RSA key pair, with the public key registered on the Snowflake user and the private key read locally from a gitignored file. Snowflake's MFA enforcement confirmed it, blocking password-only auth from a script outright, but the design didn't change because of that. The scheduled GitHub Actions runs will read the same private key from a GitHub secret.
Wait, What About Weather?
Partway through, I stopped and asked myself an obvious question I'd skipped past: doesn't next-day energy use depend heavily on temperature? A model built only on lag values and calendar features (yesterday's usage, day of week, month) has no way to know a cold snap is coming. It can only assume tomorrow looks statistically like recent days. Heating and cooling load is often the single biggest swing factor day to day, and I'd designed right past it.
So I went back into the spec before writing any of the model code. Weather is now a real input: historical temperature for training, and a live weather forecast at prediction time (since we obviously don't know tomorrow's actual temperature yet, only a forecast of it). That distinction between historical and forecast weather turned out to be its own small design decision, they come from different API calls at different pipeline stages but need to line up as the same feature to the model. I picked Open-Meteo since it covers both historical and forecast data from one provider and needs no API key, which keeps things simple on the "no secrets in this public repo" front.
The whole change flowed through the spec, research notes, data model, and task list before touching implementation, exactly the discipline spec-driven development is supposed to enforce: catch the gap, update the reasoning trail, then build.
Status
Foundational setup and the first user story (reproducible ingestion and aggregation) are implemented and tested. The spec now accounts for weather as a forecasting input, and I'm validating the Snowflake connection before moving on to building the weather-aware forecasting model itself. Follow along or check the full source on GitHub.
