Skip to content

System Design with Cursor Agent

Your startup just landed its first enterprise client. They want multi-tenant data isolation, 99.9% uptime, audit logging, role-based access control, and integration with their SSO provider. Your current architecture — a single Next.js app with a PostgreSQL database — handles your 500 existing users fine, but it was not designed for any of these requirements. You need to redesign core parts of the system without rewriting from scratch, and you need to make decisions about multi-tenancy, data isolation, and auth architecture that will either enable or constrain you for years.

System design is one of the highest-leverage activities a developer does, and one of the hardest to do well. Every decision has cascading consequences: choosing row-level tenancy vs schema-per-tenant affects your query layer, your migration strategy, your compliance posture, and your operational complexity. Cursor’s Plan and Ask modes are built for exactly this kind of exploratory, decision-heavy work — where you need to think before you build.

  • A workflow for using Plan mode to create architecture proposals before writing code
  • Prompts for evaluating trade-offs between competing design approaches
  • A strategy for generating Architecture Decision Records (ADRs) with Cursor
  • Techniques for turning high-level architecture into concrete implementation plans
  • Project rules that encode architectural decisions so Agent enforces them in code

For any architecture decision that will affect more than one service or persist beyond a single sprint, start in Plan mode. Plan mode researches your codebase, asks clarifying questions, and produces a structured plan — all before touching a single file.

Plan mode will scan your database schema, examine your auth implementation, review your API routes, and then ask targeted questions: “Do you need tenant-level database isolation for compliance, or is row-level isolation sufficient? Do your enterprise customers require data residency in specific regions?”

This back-and-forth is the most valuable part. The AI surfaces questions you might not have considered, and your answers shape the proposal.

Architecture decisions always involve trade-offs. Ask mode is the right tool for exploring them because it is read-only — no risk of premature implementation.

@scripts/schema.sql
I need to choose a multi-tenancy approach. Here are the options I'm considering:
Option A: Row-level isolation
- Add tenant_id column to every table
- Row-Level Security (RLS) policies in PostgreSQL
- All tenants share one database
Option B: Schema-per-tenant
- Each tenant gets their own PostgreSQL schema
- Shared connection pool, separate namespaces
- Migrations run per schema
Option C: Database-per-tenant
- Each tenant gets their own database
- Full isolation but complex operationally
- Higher infrastructure cost
Given our current 50-table schema, analyze:
1. Migration effort for each option (how many files change?)
2. Query complexity impact (do we need to change every query?)
3. Operational burden (backup, restore, monitoring per tenant)
4. Performance implications (connection pooling, index strategies)
5. Compliance posture (which option satisfies "data isolation"?)
6. Cost at 100 tenants vs 1,000 tenants

Ask mode will give you a thorough analysis without generating any code. You make the decision based on your specific constraints, then proceed to implementation.

@src/lib/auth @src/pages/api/auth
We need to add SSO (SAML 2.0 and OIDC) to our existing email/password auth.
Current implementation:
- JWT tokens stored in httpOnly cookies
- Custom auth middleware on API routes
- User table with email, hashed_password columns
- No concept of identity providers
Design questions:
1. Should we build SSO ourselves or use an auth provider (Auth0, Clerk, WorkOS)?
2. How do we handle users who exist with email/password and then their org enables SSO?
3. Should JIT (Just-In-Time) provisioning create users automatically on first SSO login?
4. How do we handle the case where one person belongs to multiple organizations?
5. What happens to active sessions when an org admin revokes a user's access?
For each question, give me the trade-offs of 2-3 approaches.
Don't recommend a solution yet -- I want to understand the design space first.

Once you make a decision, document it. Architecture Decision Records (ADRs) capture the context, the decision, and the consequences so future developers (and future you) understand why the system is built the way it is.

Store ADRs in your repository so Cursor can reference them. When Agent generates new code, it will consult the ADR to ensure consistency with your architectural decisions.

Once the architecture is decided, Plan mode translates it into actionable steps.

@docs/adrs/ADR-003-multi-tenancy.md @scripts/schema.sql
Based on our multi-tenancy ADR, create a detailed implementation plan:
Phase 1 (Week 1-2): Database migration
- Add tenant_id to all 50 tables
- Create RLS policies for each table
- Backfill tenant_id for existing data
- Create migration to add the tenant context function
Phase 2 (Week 3-4): Application layer
- Update the auth middleware to set tenant context
- Update all database queries to include tenant filtering
- Add tenant_id to all API request context
Phase 3 (Week 5-6): SSO integration
- Based on our auth architecture decision
- Implement SAML and OIDC flows
- Handle JIT provisioning
Phase 4 (Week 7-8): Audit and testing
- Add audit logging for all mutations
- Create tenant isolation tests
- Load test with multiple tenants
For each phase, list:
- The specific files that need to change
- The estimated effort (hours)
- The testing strategy
- The rollback plan if something goes wrong

The most impactful thing you can do after making architecture decisions is encode them as project rules. This turns your architecture from a document people read once into a constraint the AI enforces on every interaction.

.cursor/rules/architecture.md
# System Architecture Rules
## Multi-Tenancy (ADR-003)
- Every database table MUST have a tenant_id column
- Every database query MUST filter by tenant_id (no global queries except admin)
- RLS policies enforce isolation; application code provides defense-in-depth
- New API endpoints MUST accept tenant context from auth middleware
- Tests MUST verify tenant isolation (query as tenant A, verify no tenant B data)
## Authentication (ADR-004)
- Auth is handled by WorkOS for SSO, custom JWT for API tokens
- User sessions stored in signed httpOnly cookies
- JWT claims include: user_id, tenant_id, role, permissions[]
- No hardcoded roles: use permission-based checks (user.can('orders:write'))
## Data Layer (ADR-002)
- Database access goes through the repository pattern (src/repositories/)
- No direct SQL queries in route handlers or services
- All mutations must create an audit log entry
- Read replicas for analytics queries (ANALYTICS_DATABASE_URL)
## API Design
- REST with JSON responses
- All endpoints versioned (/v1/, /v2/)
- Pagination via cursor-based approach (not offset)
- Error responses follow RFC 7807 Problem Details format

With these rules active, when you ask Agent to create a new API endpoint, it will automatically include tenant filtering, permission checks, audit logging, and proper error formatting. The architecture is not just documented — it is enforced.

When your architecture needs to handle significantly more load, use Ask mode to explore scaling strategies before committing to infrastructure changes:

@src @infrastructure
Our application currently handles 1,000 requests/minute. We need to scale to
50,000 requests/minute within 6 months. Current bottlenecks based on our metrics:
1. PostgreSQL connection pool maxes out at 100 connections
2. Some API endpoints take 2+ seconds due to complex joins
3. Session validation hits the database on every request
4. Image processing blocks the request thread
For each bottleneck, propose a scaling strategy:
- What changes to architecture?
- What changes to infrastructure?
- What is the migration path from current to target?
- What can we do immediately vs what requires larger refactoring?
Consider: read replicas, connection pooling (PgBouncer), caching layers (Redis),
async processing (job queues), CDN, horizontal scaling.

Agent makes implementation decisions that contradict your architecture. This happens when your ADRs and architecture rules are not in the AI’s context. Always keep your .cursor/rules/architecture.md file updated and set to “Always Apply.” When Agent generates code that violates your architecture, point it to the specific rule: “This violates ADR-003. All queries must filter by tenant_id.”

The architecture proposal is too abstract. If Plan mode gives you vague recommendations like “use a caching layer,” push for specifics: “Which data should be cached? What cache invalidation strategy? What happens on cache miss? How does this interact with our multi-tenancy RLS?”

Trade-off analysis ignores your constraints. The AI might recommend a database-per-tenant approach that works at Google’s scale but is operationally impossible for your 3-person team. Always state your constraints explicitly: team size, budget, timeline, and operational maturity.

Architecture rules become stale. When your architecture evolves (maybe you migrate from RLS to schema-per-tenant), update the rules immediately. Stale rules are worse than no rules because they actively push Agent toward outdated patterns.

The plan is too ambitious. If Plan mode generates a 6-month implementation plan, break it into 2-week phases with clear milestones. Each phase should deliver a working system, not just pieces of a future system. Ask: “Restructure this plan so that each phase can be deployed independently and the system works correctly after each phase.”