Every early-stage startup runs into the same wall: too few engineers, too little money and a runway that shrinks every week. At QCon San Francisco, David Gudeman, co-founder and CTO of Velocity AI, used his talk to describe the technical habits that have helped him ship under exactly those conditions. InfoQ has published the recording and transcript, and the ideas are worth unpacking for any small team deciding how to build its first product.

Gudeman has spent more than a decade in companies with fewer than ten people, working as an individual contributor, product manager, engineering manager and now CTO. His central argument is simple. A startup only gets a limited number of serious attempts at finding product-market fit, so every technical decision should be judged by whether it helps the team learn and ship faster, not by whether it would impress an architect at a large enterprise.

Lesson one: pick a platform that lets you start simple and grow

For years Gudeman built everything on AWS. It gave him full control over networking and security, which made sense for an early healthcare product, but it also brought a steady drip of friction: permissions, identity configuration and a large catalog of overlapping services that each demanded research. He later inherited a product a friend had built on Firebase with very little cloud experience, expected a mess, and instead found something that worked and scaled without much effort.

That experience pushed him toward Google Cloud and Firebase as his default foundation. The key point is not that one cloud is better than another. It is that the platform should let a team begin with something almost trivially simple and then evolve it into a production-grade setup without a rewrite. In his telling, he has followed the same path three times: start with Firebase and Cloud Functions, then move the business logic into a containerized Express app on Cloud Run once the product shows signs of life. Because HTTP Cloud Functions on Firebase hand you Express-style request objects, the code largely moves over as is, and authentication stays in place.

Cloud Run gets particular praise because it sits between simple functions and a full Kubernetes cluster. It runs ordinary Docker containers, it scales down to zero when nobody is using it, and it does not require every developer to understand DevOps. One person on the team needs to learn the deployment side; everyone else can just run the service locally with Node.

He is equally clear about the limits. Velocity AI is a conversational intelligence product, and he ran into trouble trying to support WebSockets the way he wanted on Cloud Run. He also warns against fully managed one-click platforms in the Heroku mould, recalling a payment integration that demanded a very specific TLS configuration. When that kind of requirement appears and the platform has no knob for it, a small team can end up building awkward workarounds.

Lesson two: stop duplicating state on the frontend

The most opinionated part of the talk concerns frontend architecture. Gudeman considers frontend work a tar pit that teams routinely underestimate, and he sees duplicated client-side state as one of the biggest time sinks. His approach is to treat the database as the single source of truth for the UI.

In practice, the React app subscribes to Firestore queries and simply re-renders whenever the data changes. Firestore pushes updates to the client, so there is no manual cache invalidation, no refetching after mutations and no hand-built store that mirrors the database. Reads come through subscriptions; writes go through plain REST endpoints on the backend, because complex validation rules and side effects do not belong in Firestore security rules. The result is a one-way flow: the client posts a change, the backend writes to Firestore, and the UI updates itself. He estimates that, done well, this removes a substantial share of frontend code.

He pairs this with off-the-shelf component libraries such as Ant Design for complex forms and Tailwind for styling, partly because AI assistants are good at generating Tailwind markup. The message is pragmatic: if a customer insists on a feature like a reordering dialog, build it quickly with existing tools and move on rather than debating its value.

Lessons three and four: event-driven backends and background work

On the backend, his criteria are that services must be fast to build, easy to evolve and cheap to run. Cloud Run covers request-and-response work. For anything long-running, such as an AI agent processing a call transcript or a report job, he uses Pub/Sub to publish an event and Cloud Functions to consume it. That matters because, by default, Cloud Run services are billed and given CPU around request handling, so work that continues after the response is sent is not a reliable fit. Google's documentation describes instance-based billing as the option for background processing, and Cloud Run jobs exist for run-to-completion workloads, but Gudeman's pattern keeps things simple with events.

A detail small teams can borrow immediately: the background functions live in the same repository as the web service and share the same data models and helpers. There are just two entry points, one for online requests and one for event handlers. A local flag runs tasks in-process during development so engineers do not have to dig through cloud logs. Everything is deployed by a single Cloud Build pipeline on every push.

Why it matters

The talk is a useful counterweight to architecture advice written for companies with dedicated platform teams. Its value is less in the specific vendor choices than in the reasoning behind them: prefer tools that remove whole categories of work, choose services that cost nothing when idle, and make sure the simple version you ship this week can grow into the serious version you need next year without being thrown away.

There are trade-offs. Leaning heavily on Firestore ties the frontend design to one vendor's real-time model, and security rules need careful attention when clients read the database directly. Serverless platforms impose limits that may surface later, as Gudeman found with WebSockets. And a stack built around one person's experience may not suit a team with different skills.

Practical takeaways

  1. Judge platform choices by how quickly they let you ship and learn, and by whether there is a clear growth path that avoids a rewrite.

  2. Favor services that scale to zero so experiments do not quietly drain the budget.

  3. Look for ways to remove duplicated state between the client and the database; real-time subscriptions are one option.

  4. Keep writes behind a backend API where validation and side effects can be controlled.

  5. Use events and background workers for long jobs, and keep that code in the same repository with shared models.

  6. Automate deployment early so a small team never wastes time on manual releases.

For studios like ours that help startups get their first product into users' hands, the lesson rings true: speed comes less from heroic coding than from choosing foundations that let a small team keep moving.


Source: David Gudeman, QCon San Francisco talk published by InfoQ, original presentation linked below.