What to Test in a SaaS MVP: 7 Essential Checks Before Launch

Not sure what to test before releasing your SaaS MVP? Prioritize signup, activation, core workflows, billing and permissions with a practical testing strategy, runnable example and pre-launch checklist for solo developers.

A SaaS MVP can look finished and still be unsafe to release. The signup page works, the dashboard loads, and the main buttons respond. But a customer’s payment might succeed without unlocking the product, saved data might disappear after a refresh, or one workspace might be able to access another customer’s records.

These are not minor interface bugs. They affect whether someone can start using your product, get value from it, and trust it with their work.

Knowing what to test in a SaaS MVP is less about chasing a high test-coverage percentage and more about protecting the customer journeys that keep the product working.

For a solo developer, the best starting point is simple: test the paths that lead from a customer arriving at your product to successfully receiving and continuing to use its value. Then add deeper tests where a failure could expose data, lose money, or block access.

This guide gives you a practical testing strategy, a risk-based checklist, a one-week implementation plan, and a small permission-testing example you can run locally.

The first rule: test the money paths, not every button

Before choosing a testing framework, map how a customer gets value from your product.

A typical early-stage SaaS journey looks like this:

  1. A visitor creates an account.
  2. The user completes onboarding or enters a workspace.
  3. The user performs the product’s main action.
  4. The result is saved and remains available.
  5. The user returns and continues working.
  6. The user upgrades or pays, if the product is monetized.
  7. The application grants the correct access based on the account’s permissions or subscription.

Not every SaaS follows this exact sequence. A free developer tool, a paid API product, and a team collaboration application will have different customer journeys. Your own flow is the source of truth.

The useful idea is to identify the few paths where failure would prevent a customer from receiving the product’s promised value.

For an MVP, group those paths into three areas:

Critical pathWhat must workWhat failure costs
Account and activationSignup, login, onboarding and access to the correct accountA customer cannot start using the product
Core product workflowMain action, saving, retrieving and updating dataA customer cannot receive or retain value
Payment and permissionsCheckout, subscription state, roles and access boundariesLost revenue, incorrect access or exposed data

These are the first areas to protect. They are not a claim that every SaaS needs identical features or tests.

When deciding what to test in a SaaS MVP, start with the customer’s complete journey rather than testing isolated screens without knowing what they protect.

If you are still deciding which features belong in the first release, begin with how to scope a SaaS MVP and what to cut first. Testing should follow the product scope, not turn into a reason to build more features.

1. Test signup, login and account access

A user should be able to create an account, return to it, and access the correct workspace or personal data.

This sounds obvious, but authentication and authorization are different jobs. Authentication establishes who a user is. Authorization decides what that user is allowed to do.

A successful login does not prove that account permissions are correct.

What to test

Test caseExpected result
Register with valid detailsAccount is created
Register with invalid or incomplete detailsA useful validation error appears
Register with an existing emailDuplicate-account behavior is handled correctly
Sign in with correct credentialsA valid session is created
Sign in with incorrect credentialsAccess is denied
Sign outThe session is invalidated
Open a protected page while signed outThe user is redirected or denied
Open another user’s private recordAccess is denied

Also test session behavior. Reloading a page should produce the behavior your product intends. Expired sessions should not silently retain access to protected resources.

Test permissions, not just the login screen

Suppose your SaaS allows users to create workspaces and invite teammates.

A workspace might have these roles:

  • Owner: manages the workspace and its members.
  • Admin: manages most workspace settings.
  • Editor: creates and updates content.
  • Viewer: reads content but cannot change it.

Write down which operations each role can perform. Then test both allowed and blocked actions.

For example, a viewer should not be able to update a project just by sending an API request manually. Hiding the Edit button in the interface is not sufficient.

The authorization check belongs at a trusted server-side or database boundary. OWASP recommends denying access by default and validating permissions on every request. Its Authorization Cheat Sheet is a useful reference.

Release condition: A customer can sign in, access the correct account, and perform only the actions allowed by their role.

2. Test the product’s core workflow from beginning to end

Your product probably has one action that makes it worth using.

For example:

  • An invoice application creates and sends an invoice.
  • A project management application creates and updates a project.
  • A restaurant POS records an order.
  • An analytics tool collects and displays an event.
  • A document application creates and saves a document.

Test that complete action before spending time testing secondary settings.

A useful test is not simply checking whether a button works. It checks whether the intended result survives the complete workflow.

Use the create, retrieve, update and delete sequence

For a product built around records, start with these operations:

OperationWhat to verify
CreateA valid record is created with the expected values
RetrieveThe correct record can be opened again
UpdateChanges are saved and reflected on reload
DeleteThe record is removed or archived according to the product’s rules

Then test the failure cases:

  • Submit an empty required field.
  • Submit an invalid value.
  • Refresh while data is still loading.
  • Simulate a failed request.
  • Click Save twice.
  • Open a record that no longer exists.
  • Try to update a record without permission.

A success notification is not proof that a database write succeeded. Verify the result through the normal application flow or a controlled test environment.

Check persistence

One particularly useful test is:

  1. Sign in.
  2. Create a record.
  3. Wait for the save operation to finish.
  4. Refresh the page.
  5. Open the record again.
  6. Confirm that the saved data is still correct.

This catches problems that an immediate UI-only check can miss.

Also consider duplicate operations. A user may click Save twice because the interface appears slow. A browser may retry a request. A network connection may fail after the server has processed the operation.

Decide which operations must be safe to retry and test that behavior.

Release condition: A customer can complete the main job, leave the page, return, and find the expected result without duplicate or corrupted data.

3. Test billing and subscription access

If your MVP accepts payments, billing is a critical product journey.

Do not stop at testing whether the checkout page opens. The important question is whether the rest of the application responds correctly when the payment state changes.

Use your payment provider’s test environment and test the full lifecycle supported by your product.

ScenarioExpected behavior
Successful paymentThe correct subscription or entitlement is activated
Failed paymentPaid access is not granted incorrectly
Checkout cancelledThe user returns without an unintended purchase
Subscription cancelledAccess follows the cancellation policy you stated
Subscription expiresExpired entitlements are handled correctly
Duplicate payment eventThe same entitlement is not applied twice
Delayed payment updateThe product eventually reaches the correct state
User changes planThe correct account and plan are updated

Payment systems often communicate state changes asynchronously. A checkout redirect alone should not be treated as the final source of truth for subscription status.

Use the provider’s verified server-side events or API state to update entitlements. Design event handling so duplicate deliveries do not create duplicate business actions.

If your MVP is not charging users yet, test the equivalent access boundary. That might be a free usage limit, a workspace role, an invitation, or a feature available only to selected accounts.

Release condition: The product grants and removes access according to the actual account state, not merely what the browser displays.

4. Protect customer data and workspace boundaries

Data isolation deserves its own test category because a mistake here can affect more than one user.

Consider a multi-tenant application. Two customers use the same SaaS, and each has a separate workspace.

A dangerous failure would allow Customer A to retrieve Customer B’s data by changing a record ID or manipulating a request.

Test these cases:

ActorActionExpected result
User AReads a record in Workspace AAllowed if permitted
User AReads a record in Workspace BDenied
ViewerUpdates a recordDenied
EditorUpdates a permitted recordAllowed
Removed memberUses an old session to access workspace dataDenied according to the intended revocation behavior
Unauthenticated visitorCalls a protected endpointDenied

The same rules should hold through direct API requests, not only through the normal interface.

If you use Supabase, test the actual Row Level Security policies instead of assuming that filtering a query in frontend code is enough. Supabase’s RLS testing guide explains how to test policies with separate users and allowed or denied operations.

Release condition: Every private resource is protected by server-side or database-level rules, and your tests demonstrate that unauthorized access is blocked.

5. Decide what belongs in unit, integration and end-to-end tests

You do not need one kind of test for everything. Use the smallest reliable test that proves the behavior you care about.

Unit tests: individual rules

Unit tests are useful for isolated business logic.

Good candidates include:

  • Pricing calculations.
  • Trial-period calculations.
  • Usage limits.
  • Role and permission decisions.
  • Input validation.
  • Discount calculations.
  • Data transformations.

For example, if a free plan permits 100 actions per month, test the boundary at 99, 100 and 101 actions.

These tests are usually quick to run. When one fails, the problem is often easier to locate than in a long browser test.

Integration tests: connected parts

Integration tests verify that multiple parts work together.

Test things such as:

  • An API endpoint reads from the correct database.
  • A signed-in user can create a permitted record.
  • A user cannot update another workspace’s records.
  • An authorization failure produces the expected response.
  • A payment event updates the correct subscription.
  • A failed write does not produce a false success state.

These tests are especially useful where your application connects authentication, business logic, a database and external services.

End-to-end tests: real customer journeys

End-to-end tests run through the application in a browser or a production-like environment.

Examples:

  • A new user registers and reaches the dashboard.
  • A customer creates a record and sees it after a reload.
  • A viewer cannot edit a record.
  • A test customer completes checkout and receives the correct entitlement.

Use end-to-end tests for important user-visible behavior, not every tiny component interaction.

The Next.js testing guide explains the roles of unit, integration and end-to-end testing. For browser automation, Playwright’s best practices recommend testing user-visible behavior and keeping tests isolated.

Which layer should test which risk?

BehaviorUnitIntegrationEnd-to-end
Pricing calculationYesOptionalOnly if customer journey requires it
Role permission ruleYesYesTargeted test
Database ownershipNo substituteYesTargeted test
Signup journeyNoYesYes
Core record creationSome rulesYesYes
Checkout and entitlementSome rulesYesTargeted test
Page layoutUsually notRarelyVisual or browser check

Do not create three versions of every test simply to increase the test count. Choose the layer that provides the clearest evidence.

6. A small permission-testing example you can run

Here is a simple example for a workspace-based SaaS.

An active editor can read and write inside their workspace. A viewer can read but not write. An inactive member, anonymous actor, or user from a different workspace must be denied.

Create a file named access.test.mjs:

import test from 'node:test';
import assert from 'node:assert/strict';

function canAccessWorkspace({
  actorId,
  resourceWorkspaceId,
  membership,
  action,
}) {
  if (!actorId || !resourceWorkspaceId || !membership?.active) {
    return false;
  }

  if (membership.userId !== actorId) return false;

  if (membership.workspaceId !== resourceWorkspaceId) {
    return false;
  }

  const readableRoles = ['owner', 'admin', 'editor', 'viewer'];
  const writableRoles = ['owner', 'admin', 'editor'];

  if (action === 'read') {
    return readableRoles.includes(membership.role);
  }

  if (action === 'write') {
    return writableRoles.includes(membership.role);
  }

  return false;
}

const base = {
  actorId: 'user-1',
  resourceWorkspaceId: 'workspace-1',
  membership: {
    userId: 'user-1',
    workspaceId: 'workspace-1',
    role: 'editor',
    active: true,
  },
};

test('active editor can read and write', () => {
  assert.equal(
    canAccessWorkspace({ ...base, action: 'read' }),
    true
  );

  assert.equal(
    canAccessWorkspace({ ...base, action: 'write' }),
    true
  );
});

test('viewer can read but cannot write', () => {
  const context = {
    ...base,
    membership: { ...base.membership, role: 'viewer' },
  };

  assert.equal(
    canAccessWorkspace({ ...context, action: 'read' }),
    true
  );

  assert.equal(
    canAccessWorkspace({ ...context, action: 'write' }),
    false
  );
});

test('a user from another account is denied', () => {
  assert.equal(
    canAccessWorkspace({
      ...base,
      actorId: 'user-2',
      action: 'read',
    }),
    false
  );
});

test('a membership from another workspace is denied', () => {
  const context = {
    ...base,
    membership: {
      ...base.membership,
      workspaceId: 'workspace-2',
    },
  };

  assert.equal(
    canAccessWorkspace({ ...context, action: 'read' }),
    false
  );
});

test('inactive membership is denied', () => {
  const context = {
    ...base,
    membership: { ...base.membership, active: false },
  };

  assert.equal(
    canAccessWorkspace({ ...context, action: 'read' }),
    false
  );
});

test('anonymous actor is denied', () => {
  assert.equal(
    canAccessWorkspace({
      ...base,
      actorId: null,
      action: 'read',
    }),
    false
  );
});

test('unknown actions are denied', () => {
  assert.equal(
    canAccessWorkspace({ ...base, action: 'delete' }),
    false
  );
});

Run it with:

node --test access.test.mjs

This example uses Node’s built-in test runner, documented in the Node.js test runner reference.

Verification: The example was executed separately with Node.js v22.16.0. All seven tests passed.

There is an important limitation: this helper tests a permission decision in isolation. It does not secure a production application by itself. In a real SaaS, membership information must come from a trusted server-side or database source. Enforce the rules at the server or database boundary and test those real boundaries too.

7. The one-week testing plan for a solo developer

You do not need to introduce a large testing framework in one day. Work through the highest-risk behavior first.

Day 1: Map the critical journeys

Write down the paths from account creation to first value, the core product action, and payment or access.

For each, record:

  • Starting condition.
  • User action.
  • Expected result.
  • One important failure condition.
  • Evidence that proves the result.

Use your product requirements as the source of expected behavior. If the requirements are unclear, fix that before writing tests.

A useful starting point is to turn your PRD for an AI coding agent into explicit acceptance criteria, then use a technical specification to define implementation boundaries.

Day 2: Test business rules

Start with pricing, role permissions, validation, limits and other pure logic.

Write a small number of clear tests for valid inputs, invalid inputs and important boundary values.

Day 3: Test database and API boundaries

Create tests for record ownership, workspace separation and invalid requests.

Use test users and an isolated database or staging environment. Do not run destructive tests against real customer records.

Day 4: Test billing and other external services

When billing exists, use the provider’s test environment. Check payment success, failure, cancellation, event duplication and delayed updates.

Also check any other external service that can block the product’s main workflow.

Day 5: Automate the main customer journeys

Add browser tests for the most important flows.

Start with a successful signup and core workflow. Add a small number of failure paths such as an unauthorized edit or an unsuccessful checkout.

Day 6: Run checks consistently

Add the actual verification commands used by your project to your normal development and CI workflow.

For example:

npm run lint
npm run typecheck
npm run test
npm run build

These are examples, not commands that every project automatically supports. Check your package.json and configure the scripts you actually need.

Day 7: Run a staging smoke test

Use a staging environment that resembles production.

Test the important journeys again. Confirm that test accounts and payment credentials are isolated from production. Check that application errors and failed background tasks are visible to whoever maintains the product.

A week is a starting schedule, not a deadline. A complex product may require more time.

8. What you can postpone

A solo developer can lose days trying to make a test suite look impressive.

For the first release, avoid treating these as blockers unless your product’s risk justifies them:

  • A 100% code-coverage target.
  • End-to-end tests for every button and menu.
  • Snapshot tests for every component.
  • Large-scale load testing without a realistic traffic requirement.
  • Complex test infrastructure that takes longer to maintain than the product.
  • Tests that depend on a shared database with changing data.
  • Testing the internal behavior of third-party libraries you do not control.

This does not mean these techniques are useless. Add them when usage, complexity, customer expectations or the consequences of failure make them worthwhile.

Coverage is useful for finding untested code. It does not prove that the most important customer behavior is correct.

9. What monitoring can and cannot replace

Monitoring and testing work together, but they answer different questions.

A test asks: Does this behavior work under the conditions I specified?

Monitoring asks: What is happening when the application is running?

Useful monitoring for an early SaaS includes:

  • Failed API requests.
  • Unexpected server errors.
  • Failed payment updates.
  • Background jobs that stop running.
  • Unusual database errors.
  • Failed signup or onboarding operations.
  • Spikes in errors after a release.

Monitoring helps you discover failures that your tests missed. It cannot replace a test that verifies whether a user is allowed to access a private record.

For example, a dashboard may tell you that API errors increased after deployment. It will not prove that a viewer cannot update an editor-only record.

Build both into your release process.

10. The SaaS testing checklist before launch

Use this list to review the product. Mark an item complete only after performing the check and seeing the expected result.

Account and activation

  • A new user can register.
  • Existing users can sign in and sign out.
  • Protected routes reject unauthenticated users.
  • Session expiry behaves as expected.
  • Users cannot access another account’s private data.

Core product workflow

  • The main product action completes successfully.
  • Created data remains available after a reload.
  • Records can be retrieved and updated.
  • Invalid input is handled correctly.
  • Failed operations do not display false success messages.
  • Repeated submissions do not create unwanted duplicate records.

Billing and permissions

  • Successful payment grants the correct entitlement.
  • Failed or cancelled payments do not grant unintended access.
  • Subscription changes update the correct account.
  • User roles are enforced on the server or database.
  • Inactive members cannot retain access beyond the intended policy.
  • Cross-workspace access attempts are denied.

Release verification

  • Relevant unit tests pass.
  • Database and API integration tests pass.
  • Critical end-to-end tests pass.
  • Linting and type checks pass, if configured.
  • The production build succeeds.
  • Critical journeys work in staging.
  • Important runtime errors are visible to the maintainer.

Frequently asked questions

What should I test first in a SaaS MVP?

Start with signup and activation, the core product workflow, and payment or permissions. These paths determine whether customers can enter the product, get value, and access only what they should.

How much test coverage does an MVP need?

There is no universal coverage percentage that makes an MVP ready. Focus on whether the tests protect the important business rules, customer journeys, data boundaries and payment behavior. Use coverage to find gaps rather than treating it as the definition of quality.

Should I write unit tests or end-to-end tests first?

Start with the highest-risk rules and boundaries. Unit tests are useful for isolated business logic, integration tests are useful for database and API behavior, and end-to-end tests are useful for complete customer journeys. Most MVPs benefit from a small combination rather than choosing only one type.

Can monitoring replace automated testing?

No. Monitoring helps identify problems in a running application. Automated tests check expected behavior before a change reaches customers. Neither replaces the other.

Should I test every feature before launch?

Prioritize features that protect customer data, money, access and the product’s main promise. Lower-risk features can receive lighter checks until usage or business requirements justify deeper coverage.

Which testing tools should a Next.js SaaS use?

The current Next.js testing documentation provides setup guidance for tools such as Vitest and Playwright. Vitest is useful for unit testing, while Playwright is designed for browser-based end-to-end tests. Check the framework’s current limitations when choosing a setup, especially for asynchronous Server Components.

Final thought

You do not need the biggest test suite to release a reliable SaaS MVP. You need evidence that the product’s most important journeys work, that customer data remains isolated, and that permissions and payments behave as intended.

Start with the paths that create and protect customer value. Add the right tests at the right layer, run them consistently, and use monitoring to catch what automation misses.

That is a more useful definition of testing progress than a coverage percentage alone.

Unit and end-to-end tests are only part of a safe release. Before merging a feature written with an AI coding agent, use our AI-generated code verification checklist to inspect the complete diff, challenge the tests and review security boundaries.

Sources and further reading

Shreyansh
Shreyansh

3 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *