# We caught an architecture mistake in our own spec before it shipped.

> Source: <https://dev.to/akshay_sharma_06637368320/we-caught-an-architecture-mistake-in-our-own-spec-before-it-shipped-4n14>
> Published: 2026-09-07 10:15:14+00:00

We caught an architecture mistake in our own spec before it shipped.

The early draft of the Cadencz backend spec assumed Next.js could carry both the frontend and a chunk of the product API, using its `/app/api` routes as a shortcut. On paper it saves a service. In practice it quietly merges two things that should stay apart.

The correction we made: Next.js is frontend only. No product API lives inside it. A separate backend owns every OAuth callback, every billing webhook, every scheduling state change, every AI credit check.

This isn't a framework preference. It's about what each of those things actually needs.

OAuth callbacks need a stable, versioned endpoint that doesn't move when someone redesigns a page. Billing webhooks from a payment provider need a service that can retry, log, and stay up even if the frontend deploy is mid-rollout. Scheduling state changes need a source of truth that isn't tied to a request/response cycle built for rendering HTML.

Mixing these into the same codebase as your UI works fine until you need to redeploy the frontend without touching billing logic, or debug a failed webhook without wading through page components. Then the coupling shows up as an incident, not a code smell.

The tradeoff is real. Two services mean two deploy pipelines, two places to monitor, and more upfront setup than a monolith. For a weekend project, that overhead isn't worth it.

For anything that touches money or third-party auth, it is. A billing webhook failing silently because your frontend build broke is a worse outcome than the extra infrastructure it takes to prevent it.

The lesson generalizes past this one stack. Frontend and backend separation is a decision you make based on what your system touches, not a default you inherit from a tutorial. If your app never handles payments or OAuth, a combined setup might be the right call. If it does, treat the split as a requirement, not a nice-to-have.

What would you add? Where has skipping this separation actually bitten you in production?
