When Switzerland opened the door to Lokale Energiegemeinschaften in 2025, most of the conversation was about solar panels and lower bills. Fair enough. But the product we had to build wasn’t a landing page with a signup form. It was a platform where grid operators exchange metering data on fixed schedules, allocation runs on fifteen-minute intervals, invoices carry Swiss QR-bill references, and a wrong VAT line is a customer complaint and an accounting problem.
I co-founded Upgrid as CTO in January 2025. The job wasn’t “build an app.” It was build the billing, allocation, and operator workflows that make community energy legally and financially real — and ship fast enough to matter while Swiss reform was still fresh.
Real money on real invoices. Same correctness bar I learned at N26, different domain.
Upgrid operates in Swiss energy law: ZEV, LEG, and vZEV community models each carry different metering, allocation, and billing rules. The platform has to support all of them without pretending they’re the same workflow with different labels.
Who the platform serves
Every product decision at Upgrid starts with who you’re optimizing for. Consumers want zero friction. On the supply side we support three operator models — and they want opposite things from the same codebase:
Zero-friction signup. Find a community, understand the savings, sign a contract, done. They will not read a manual about Swiss grid topology.
Grid operators and energy retailers running communities end-to-end: community formation, meter wiring, allocation review, invoice generation, Bexio sync, exception handling. They live in the product daily.
Municipalities and solar installers who bring members but don't run billing themselves — Upgrid operates the communities on their behalf. Branded join flows and contract-intent triage, one platform underneath.
Partners who refer consumers and earn a cut. No operator console, no community management — just tracked signups and attribution. Lightweight by design.
As CTO I own the architecture, but I also act as PM and marketing when the bottleneck is clarity — not code. That means savings calculators, LEG explainer content, signup funnel instrumentation, and operator onboarding UX all land on the same roadmap as Postgres migrations.
The architecture bet: monorepo at small-team scale
At N26 I spent years inside a ~200-service estate. The most valuable work I did there was often consolidation — pulling scattered fraud rules into one stateful stream because distribution was causing latency, not defending against it.
Upgrid is the opposite call. We’re a small team shipping a regulated, money-handling platform. A 37-package monorepo with shared types, one Postgres schema, and one CI pipeline beats microservice coordination when real coupling is high and team size is low.
- High team count — service boundaries match org boundaries
- Distributed state stitched across Kafka topics and REST calls
- Deploy coordination across dozens of repos
- Consolidation became the performance win
- Small team — shared schema and types reduce integration tax
- One Postgres database with RLS multi-tenancy
- Single CI pipeline with ratchets, not big-bang migrations
- Coupling is real; pretending it's microservices wouldn't help
Team size and actual coupling decide topology. Not fashion.
The money path
Community energy isn’t CRUD. The path from grid data to customer invoice crosses ingestion, allocation, billing, PDF generation, and accounting sync — and every step has a Swiss-specific rule attached.
A UI typo is embarrassing. A wrong allocation on a large vZEV community is an OOM crash, a support ticket, and a recalculation job. A wrong VAT line on a Swiss QR-bill is an invoice dispute. We treat the money path with the same paranoia I brought from financial crime prevention — observability on ingestion, idempotent jobs, and tests on the billing engine before we polish marketing pages.
Contract intents vs live contracts is another example. A prospect signing up through a co-brand operator or affiliate link isn’t a billing customer yet. Mixing those lifecycles in one table would have been convenient and wrong. We separated them early — distinct states, distinct workflows — because retrofitting domain boundaries after invoices exist is expensive.
Engineering multipliers
Raw commit counts don’t compound. Infrastructure and practices do. These are the decisions that let a small team ship like a larger one without lowering the correctness bar.
An internal agent in Slack — schema digest, versioned metric definitions, codebase index, read-only connectors to production data, Linear, and PostHog. Ops and product can ask whether a meter is receiving data or how signup traffic looked this month without interrupting an engineer.
CDKTF stacks for Better Stack monitors and heartbeats on the SDAT ingestion pipeline, plus PostHog feature flags defined in the repo and deployed via GitHub Actions. Observability and rollout config are versioned and reviewable — not click-ops in vendor UIs.
Triple sync: infrastructure definitions, application constants, and a CI check that fails if they drift. The same PostHog project that powers GTM analytics also gates bill-upload onboarding, operator features, and landing-page experiments.
A layered data-access ADR with a check that fails CI on new direct database calls while grandfathering legacy sites. Architecture improves weekly without a big-bang rewrite or winning arguments in meetings.
Business metric definitions live as YAML in the product repo and sync downstream. The company brain queries known metrics — communities, contracts, meter readings — without ad-hoc SQL every time someone asks a question.
AGENTS.md, Cursor rules, migration gates, and test requirements in CI. AI-assisted delivery is safe to merge in money-handling code because the guardrails are encoded, not implied.
- Feature flags toggled in vendor UI — no PR, no review
- Monitors configured by hand — drift from prod
- Architecture debates in Slack — no enforcement
- Ops questions routed to whoever is online
- Flags in IaC + app code + CI sync check
- Monitors and heartbeats in Terraform state
- Ratchets fail CI on new violations only
- Company brain answers from live indexed knowledge
ADR or flag definition in infrastructure config. App constants and preload list updated in the same PR.
check:feature-flags and check:data-access run on every pull request. Drift fails the build.
Gradual flag rollout or PostHog experiment. Operator features ship dark; consumer flows get A/B variants.
Funnel events, field errors, abandonments — same instrumentation stack as GTM analytics.
The unglamorous work matters too: locale drift checks, Supabase typegen drift detection on PRs, migration timestamp validation. Nobody writes blog posts about those. They keep a monorepo honest.
Applied AI — shipped, not demoed
I’ve seen too many “AI-native” pitches that mean “we use Copilot.” Upgrid has three layers, ordered by who benefits:
- Chatbot on the marketing site
- Internal Slack bot with no prod access
- Copilot with no CI gates on output
- No connection to business metrics
- Bill-upload pre-fill: customer uploads energy bill, LLM extracts fields, form arrives populated
- Company brain: ops self-serve against live data and indexed schema
- Agent harness: migration rules, test gates, touch-it-migrate-it policy in CI
The highest-friction step in consumer onboarding is typing your meter details correctly. We run bill extraction through the Vercel AI Gateway with structured output and validation before anything hits the contract intent. PostHog tracks the full bill-upload funnel — upload started, extraction succeeded, fields accepted — alongside the join flow.
Layer one is customer-facing. Layer two is company-facing. Layer three is engineering-facing. All three need guardrails; only the first two need to work when I’m not in the room.
Beyond the keyboard
Engineering multipliers don’t matter if nobody signs up. As co-founder I spent serious time on go-to-market: a savings calculator, LEG reform content, SEO guides, co-brand landing pages for municipalities and installers, affiliate attribution, and signup instrumentation built like production software.
Referral, direct, organic social, paid search, and organic search — no single growth hack. Co-brand pages for municipalities and installers, affiliate links, and Upgrid-owned SEO content all feed the same join flow.
join_community.* events track steps, field errors, abandonments, and CTA clicks — not just pageviews. The taxonomy grew over time; early dashboards undercounted what we can measure today.
Contract intents from web, operator-assisted onboarding, and partner channels. Product scale is north of two thousand members — web-only funnel snapshots never captured the full picture.
Auto-selection, operator triage, contract intent → live contract when preconditions are met.
- Pageviews only — no funnel steps
- Experiments configured separately from flags
- GTM and engineering use different tools
- No field-level error tracking
- Rich join_community.* event taxonomy
- Same PostHog project for flags and funnels
- Bill-upload and contract_intent.* operator events
- Funnel conversion and drop-off measured in-product
2k+ members, 250+ communities, and 150+ municipalities on upgrid.ch are the numbers worth quoting — they reflect actual product scale. PostHog is how we iterate on the join flow week to week, but the event taxonomy evolved; point-in-time funnel exports from early instrumentation undercount submissions that came through operator onboarding, co-brand partners, and channels we hadn’t wired yet.
What I’d do again / differently
SDAT is the root of the money path. Better Stack monitors and heartbeats should have shipped with the first ingestion job, not after the first silent failure.
Metering formats and allocation inputs change. Version the contracts, fail loudly on drift, and document them where the company brain can find them.
Operators live in the product. A beautiful consumer landing page doesn't help if community formation and billing exceptions are painful.
Feature flags and PostHog experiments are multipliers — use them for join flows, bill upload, and operator features instead of debating in meetings.
Local energy is a systems, regulation, and go-to-market problem — not a landing page. The teams that win will be the ones who treat billing correctness and signup instrumentation with the same seriousness as fintech treats fraud.