Retrospective.fun is a real SaaS with real users, not a demo project. It runs on .NET 8, Angular 20, PostgreSQL (with pgvector), and a fairly opinionated CQRS + event sourcing setup.

The unusual part is that almost all of the implementation (controllers, domain handlers, event projections, Angular components, background workers) was written by AI tools. My role was to design the system and keep the architecture consistent.

This is a summary of how that worked, what needed human judgment, and where AI saved me a lot of time.


Why I tried this approach in the first place

I wanted to find out whether an experienced developer could realistically build production software with AI doing most of the implementation, as an actual sustainable workflow rather than a stunt.

I'd been running an internal version of retrospective.fun for years. It worked well enough for my teams, but the architecture wasn't scalable or sellable. I knew what it needed (session memory, proper CQRS, real multi-tenancy), and a complete rewrite would have taken months I didn't have.

Then AI agents got good enough to change the maths. They aren't much use inventing a system from scratch, but for rebuilding one I already understood inside out, they were fast.

This is what that rebuild looked like.


Architecture first, always

For AI to work at this scale, the structure has to be extremely predictable.

I leaned on:

  • event sourcing for all domain aggregates
  • CQRS read models for the UI
  • strict naming and handler conventions
  • a single-session content model instead of multiple aggregates
  • background workers for anything long-running
  • generated TypeScript API clients
  • Angular signal stores for state

Once these patterns were in place, AI tools did a good job following them.

When they weren't in place, the AI wandered.


How the workflow actually looked

A typical feature went like this:

  1. I wrote a short spec: the intent, the API surface, constraints
  2. I outlined the events, commands, and changes to the read model
  3. AI generated the aggregate code, controller endpoint, projection handler, and tests
  4. I fixed naming, edge cases, and off-by-one errors
  5. I ran the app and saw where UX or logic needed adjusting

I owned the design. The AI owned the tedious parts.

The closest comparison is working with a very fast junior developer who follows patterns obsessively and never gets bored.


The issue-tracking system: context is everything

Getting AI to write code turned out to be the easy half. The harder half was building the scaffolding that kept agents focused once the project got big.

Early on I hit a wall: AI agents couldn't handle large markdown files with multiple issues. They'd lose context, duplicate work, or skip requirements.

So I started simple: three folders (backlog, in-progress, done) and a planning board.

Then I asked AI to write convenience scripts to move issues between folders. Then scripts to filter and sort. Then RICE scoring. Then release planning with themes and effort tracking.

What emerged is a project management system built for AI consumption rather than human browsing:

  • YAML frontmatter with RICE scores, effort estimates, dependencies, risk categories, release IDs
  • structured workflow with automatic timestamp tracking
  • smart filtering by priority, effort, release, labels, or RICE score
  • release themes that group related work without rigid sprints
  • real-time documentation expectations built into every issue

The issue files themselves became the single source of truth. When an agent starts work, it reads one markdown file with everything it needs: acceptance criteria, technical context, dependencies, and a clear place to log progress.

No context switching, no hunting through chat history, no "wait, where was I".

It compounds. AI wrote the tooling, the tooling made AI more effective, and more effective AI could handle more complex tooling. Each turn of that unlocked slightly harder problems.

The system is now as much a part of the product as the application code.

Better prompts and bigger context windows helped less than I expected. What worked was building an environment the agents couldn't get lost in.


The parts where AI shined

Repetitive glue code

Event handlers, repository methods, read model projections, DTO mapping. All excellent candidates for AI.

Large refactors with clear patterns

When I consolidated multiple aggregates into a single SessionContent model, AI handled most of the mechanical changes consistently.

Background workers and services

Anything that follows a known pattern (timers, embedding jobs, API wrappers, rate limiting) was easy for AI to implement once the structure was in place.

Test generation

Especially for command handlers and controllers, as long as the acceptance criteria were clear.


The parts where AI struggled

Cross-cutting changes

Anything touching many layers conceptually, like moving from MongoDB to PostgreSQL with RLS, required careful manual planning. AI helped with the implementation, but the orchestration had to be mine.

Business rules

The AI can read code, but it doesn't understand why something matters. Stage logic, tier limitations, GDPR rules. These needed explicit guidance.

Performance

I had to profile first, then guide the AI to rewrite heavy queries or N+1 patterns. It won't optimise anything on its own initiative.

UX and flow

AI can implement UI, but not design it. You still need to decide what a clean flow feels like.


The AI reliability layer

I didn't want the app randomly calling OpenAI for every little thing, or failing silently.

So there's a reliability layer in front of all AI features:

  • idempotency caching
  • rate limiting
  • circuit breakers
  • retries with backoff
  • strict timeouts

AI wrote most of that code, but only after I specified the rules clearly.

It keeps costs predictable and avoids surprises.


Semantic search with pgvector

Retrospective.fun also stores embeddings for notes, discussion points, and actions. A background worker handles all embedding generation with deduplication and batching, and the system can surface similar topics within or across sessions.

Again, typical structured work that AI is good at once you've decided how it should behave.


What helped the most

A few principles made this manageable:

  • Make patterns explicit. If the AI sees the same structure everywhere, it won't go inventing new ones.
  • Keep the domain small and focused. A single-session content model made everything downstream easier.
  • Write short, clear specs. The AI doesn't need essays, it needs constraints.
  • Review everything. It's still your name on the product.

What I'd repeat on the next project

I'd absolutely use this approach again, with the same boundaries:

  • Humans handle architecture, UX, and decisions
  • AI handles implementation details
  • CI/CD and documentation do the rest

Nobody gets a SaaS built for free here. What you get is a multiplier, and only if your structure is sound.

Retrospective.fun isn't perfect, but it's in production with paying teams, and the development workflow has been surprisingly sustainable.

If you're a developer or founder thinking about trying this: start with the architecture, keep the patterns tight, and put real effort into the tooling that feeds AI its context. The repetitive work goes to the AI. The decisions stay with you.

That's the setup that made this project viable for me.