← Back to list

I Built a SaaS Product Using Only Cursor and Claude. The Surprising Part Wasn’t the Code.

The era of small teams isn’t coming. It’s already here.

Neurobyte · 2026-07-07 04:31 · 19 claps · 5.4 min read paywalled
#ai-engineering #ai #cursor-ai #claude-ai #productivity
Open on Medium ↗
Wiki topics: LLM · Large Language Models AI · AI · General ⏱️ · Productivity

I Built a SaaS Product Using Only Cursor and Claude. The Surprising Part Wasn’t the Code.

The era of small teams isn’t coming. It’s already here.

I built a SaaS product using only Cursor and Claude. Here’s what actually happened, what broke, and why software engineering is changing.

Three years ago, this headline would have sounded ridiculous.

Today, it’s barely controversial.

I recently built a SaaS product using almost nothing except Cursor and Claude. No engineering team. No dedicated frontend developer. No backend specialist. No DevOps engineer.

Just me.

And here’s the part most people get wrong:

The difficult part wasn’t generating code.

The difficult part was making decisions.

AI removed perhaps 80% of the typing.

It removed almost none of the thinking.

That’s an important distinction.

Because while everyone is debating whether AI will replace developers, something far more interesting is happening:

AI is replacing the parts of software development that were never the bottleneck.

Software Development Was Never About Writing Code

Most developers secretly know this.

The code itself is rarely the hard part.

The hard part is deciding:

  • What should exist
  • What should not exist
  • Which tradeoffs matter
  • Which complexity is unavoidable
  • Which complexity is self-inflicted

Before AI, these decisions were buried under weeks of implementation work.

Now they’re exposed.

Painfully exposed.

Cursor can generate a CRUD API in minutes.

Claude can design database schemas faster than most engineers can sketch them on a whiteboard.

But neither tool knows:

  • What your customers actually need
  • Which features generate support tickets
  • Which architecture decisions become technical debt six months later

Those are still human problems.

The First Mistake AI Helped Me Make Faster

The SaaS product started small.

A fairly straightforward workflow:

Users submit requests.

Background jobs process them.

Results appear in a dashboard.

Simple.

Or so I thought.

Within hours Cursor had generated:

  • FastAPI services
  • PostgreSQL models
  • Docker configuration
  • Redis caching
  • Authentication flows

The velocity felt magical.

Then I looked at the architecture.

Claude had essentially built what looked like a startup preparing for 50 million users.

I had zero users.

Classic engineer mistake.

Just executed faster.

The Architecture I Almost Shipped

The AI-generated version looked something like this:

                     API Gateway
                          |
        ----------------------------------
        |               |               |
 User Service    Billing Service   Job Service
        |               |               |
        ----------------------------------
                          |
                    Kafka Cluster
                          |
        ----------------------------------
        |               |               |
 Email Worker    Analytics Worker  Audit Worker

Looks impressive.

Also completely unnecessary.

I wasn’t building Stripe.

I was building an MVP.

Every service boundary creates:

  • deployments
  • monitoring
  • debugging overhead
  • operational complexity

The architecture was solving problems I didn’t have.

What I Built Instead

A modular monolith.

The most underrated architecture pattern in software engineering.

             FastAPI Application
                       |
    ---------------------------------------
    |           |           |             |
  Users      Billing      Jobs        Admin
    |           |           |             |
    ---------------------------------------
                     PostgreSQL
                           |
                        Redis

One deployment.

One database.

One repository.

Clear module boundaries.

Zero distributed systems headaches.

The product launched weeks faster because of this decision.

Not because of AI.

Because of judgment.

Lesson #1: AI Makes Good Decisions More Valuable

When implementation becomes cheap, architecture becomes expensive.

That’s the paradox.

A junior developer can now generate 5,000 lines of code before lunch.

A bad architectural decision can still cost six months.

Nothing changed there.

Idempotency Is More Important Than Ever

AI generated my first payment workflow.

It looked clean.

It was also broken.

Bad Implementation

@app.post("/payments")
async def create_payment(payment: PaymentRequest):

    await db.execute(
        """
        INSERT INTO payments(user_id, amount)
        VALUES ($1, $2)
        """,
        payment.user_id,
        payment.amount
    )

    return {"status": "success"}

Looks fine.

Until:

  • network retries happen
  • client requests duplicate
  • browser refreshes
  • mobile reconnections occur

Now customers get charged twice.

Not great.

Production Version

@app.post("/payments")
async def create_payment(
    payment: PaymentRequest,
    idempotency_key: str = Header(...)
):

    existing = await db.fetchrow(
        """
        SELECT *
        FROM payments
        WHERE idempotency_key = $1
        """,
        idempotency_key
    )

    if existing:
        return existing

    payment_record = await db.fetchrow(
        """
        INSERT INTO payments(
            user_id,
            amount,
            idempotency_key
        )
        VALUES ($1, $2, $3)
        RETURNING *
        """,
        payment.user_id,
        payment.amount,
        idempotency_key
    )

    return payment_record

AI generated both versions.

Only one survives production.

Async Workflows Beat Synchronous Dreams

Every beginner SaaS architecture eventually reaches the same moment.

The request starts taking too long.

Users click refresh.

Everything breaks.

My original endpoint looked like this:

@app.post("/generate-report")
async def generate_report():

    report = expensive_report_generation()

    send_email(report)

    upload_to_storage(report)

    return report

Response time:

12–18 seconds.

Terrible.

The fix:

@app.post("/generate-report")
async def generate_report():

    job_id = str(uuid.uuid4())

    await redis.lpush(
        "report_queue",
        json.dumps({"job_id": job_id})
    )

    return {
        "job_id": job_id,
        "status": "processing"
    }

Worker:

while True:

    job = redis.brpop("report_queue")

    process_report(job)

    update_status(job["job_id"])

Now requests finish in milliseconds.

Users feel speed.

Infrastructure feels relief.

Everybody wins.

The Outbox Pattern Saved Me From Data Corruption

Distributed systems don’t fail dramatically.

They fail quietly.

Imagine:

create_invoice()

publish_event()

What happens if the database write succeeds but the event fails?

You now have inconsistent state.

The worst kind of bug.

Instead:

with db.transaction():

    create_invoice()

    insert_outbox_event(
        event_type="invoice_created"
    )

Background worker:

while True:

    events = get_pending_events()

    for event in events:

        publish(event)

        mark_processed(event.id)

This pattern has existed for years.

Yet AI-generated code rarely includes it by default.

Because most examples online don’t.

That’s a fascinating lesson.

AI inherits the internet’s average quality.

Not its best practices.

Observability Is the New Superpower

AI can generate code.

AI cannot explain a production outage at 3:17 AM.

For that you need visibility.

Every service should emit structured logs.

logger.info(
    "payment_processed",
    user_id=user.id,
    payment_id=payment.id,
    amount=payment.amount
)

Bad logs:

logger.info("success")

Successful what?

Nobody knows.

Especially future you.

Metrics matter too.

payment_counter.inc()

request_duration.observe(
    processing_time
)

You can’t optimize what you can’t see.

And most performance problems aren’t where engineers think they are.

Redis Was Worth More Than Most Refactors

Developers love rewriting systems.

Users love fast applications.

Different priorities.

A simple cache reduced database load dramatically.

cached_user = await redis.get(
    f"user:{user_id}"
)

if cached_user:
    return json.loads(cached_user)

user = await get_user(user_id)

await redis.setex(
    f"user:{user_id}",
    300,
    json.dumps(user)
)

return user

Five minutes of caching.

Weeks of scaling postponed.

Rate Limiting Is a Feature, Not a Security Layer

The first public launch brought bots.

Of course it did.

Simple protection:

from slowapi import Limiter

limiter = Limiter(
    key_func=get_remote_address
)

@app.post("/api/search")
@limiter.limit("100/minute")
async def search():
    ...

One line.

Huge difference.

Sometimes engineering isn’t about sophistication.

It’s about restraint.

Why Teams Historically Overengineered Everything

This isn’t an AI problem.

It’s an industry problem.

For years, developers learned architecture from companies like:

  • Netflix
  • Uber
  • Amazon

The problem?

They were solving problems at extraordinary scale.

Most startups aren’t.

Most SaaS products never will.

Yet teams copied:

  • microservices
  • event meshes
  • service discovery
  • distributed transactions

before finding product-market fit.

The result wasn’t scalability.

The result was meetings.

Lots of meetings.

Microservices vs Monolith: The Conversation AI Changed

AI made implementation cheap.

Which means coordination became the dominant cost.

A microservice architecture introduces:

Service A -> Service B -> Service C

Every arrow is:

  • latency
  • failure risk
  • deployment complexity
  • debugging effort

For small teams, modular monoliths often outperform distributed architectures.

Not because they’re fashionable.

Because they’re efficient.

Most scalability problems are coordination problems wearing a CPU costume.

When This Advice Fails

There are absolutely situations where complexity is justified.

Examples:

  • Hundreds of engineers
  • Independent deployment requirements
  • Massive traffic volumes
  • Strict compliance boundaries
  • Multiple autonomous teams

At that point:

  • Kafka makes sense
  • Service boundaries matter
  • Event-driven systems pay off

The mistake is adopting enterprise architecture before enterprise problems arrive.

What Smart Teams Are Actually Doing Today

The strongest engineering teams I’ve seen recently tend to follow a surprisingly similar stack:

Application

  • FastAPI
  • Next.js
  • TypeScript

Database

  • PostgreSQL

Cache

  • Redis

Queue

  • RabbitMQ or lightweight Kafka usage

Infrastructure

  • Docker
  • Managed cloud services

Monitoring

  • OpenTelemetry
  • Prometheus
  • Grafana

Architecture

  • Modular monolith first
  • Extract services only when necessary

Notice what’s missing.

Complexity.

Not because complexity is bad.

Because unnecessary complexity is expensive.

The Unexpected Truth About Building With Cursor and Claude

People think AI changes software engineering because it writes code.

I think it changes software engineering because it exposes thinking.

The implementation bottleneck is collapsing.

The judgment bottleneck isn’t.

Cursor generated thousands of lines.

Claude generated architecture suggestions.

Both accelerated execution dramatically.

Neither replaced engineering.

If anything, they amplified it.

Because every decision now arrives faster.

Good ones and bad ones.

And that means the developers who thrive won’t be the fastest typists.

They’ll be the best decision makers.

The future isn’t developers versus AI.

It’s developers with leverage versus developers without it.

And leverage has never been the same thing as wisdom.

That’s still a human skill.

For now.


메타데이터
post_id
aa07e97d7bf2
slug
i-built-a-saas-product-using-only-cursor-and-claude-the-surprising-part-wasnt-the-code-aa07e97d7bf2
url
https://medium.com/@kaushalsinh73/i-built-a-saas-product-using-only-cursor-and-claude-the-surprising-part-wasnt-the-code-aa07e97d7bf2
canonical_url
https://medium.com/@kaushalsinh73/i-built-a-saas-product-using-only-cursor-and-claude-the-surprising-part-wasnt-the-code-aa07e97d7bf2
author_url
https://medium.com/@kaushalsinh73
status
ok
fetched_at
2026-07-07 13:53:00