Privacy-respecting analytics

Joh uses Google Analytics to understand which stories and portfolio pages are useful. Advertising storage stays off. Read the privacy notice.

Joh Azores

Free practical resource

Software product architecture audit checklist

Use this checklist to review an existing SaaS, Next.js, WordPress, dashboard, CMS, membership, API, or full-stack product before planning a rewrite or adding more architecture.

Download Markdown checklist

Use evidence

Base findings on source code, production behavior, user workflows, support history, analytics, and operations.

Prioritize trust

Correctness, security, lead loss, data risk, and production reliability come before cosmetic refactoring.

Avoid the rewrite trap

Preserve working systems and change only what improves clarity, maintainability, performance, or outcomes.

1

Product and business context

Confirm the technical work is connected to a real user, operating, or revenue problem.

The primary users and their most important workflows are documented.

The current business goal, success criteria, and major constraints are clear.

Production-critical workflows are separated from experiments and optional features.

Known customer complaints, support volume, and operational pain are included in prioritization.

The roadmap distinguishes urgent risk, maintenance, product improvements, and new bets.

2

Architecture and boundaries

Make the system understandable before adding abstractions or replacing working parts.

Application, domain, data, integration, and infrastructure responsibilities are easy to trace.

Server, client, API, background, and external-service boundaries are intentional.

Repeated business rules and validation are centralized at the correct boundary.

Shared modules are genuinely reused and do not hide simple behavior behind generic frameworks.

Legacy and transitional paths have an owner, reason, and removal condition.

3

Code health and maintainability

Reduce the cost and risk of future changes without refactoring for appearance alone.

Dead code, unused files, duplicate utilities, and obsolete feature flags are identified.

Components and functions have one understandable responsibility.

Naming reflects the product domain rather than implementation accidents.

Dependencies are justified by current usage and not only by historical setup.

Documentation describes the current system and excludes completed milestone notes.

4

User experience and accessibility

Evaluate whether important work is understandable and usable across real devices and input methods.

The first screen explains the users next action and the product value clearly.

Critical workflows work at 320px, 375px, tablet, laptop, and large desktop widths.

Keyboard navigation, focus order, focus return, Escape handling, and labels are verified.

Loading, empty, validation, error, success, and permission states are intentionally designed.

Forms minimize unnecessary questions and preserve useful context when errors occur.

5

Performance and rendering

Measure the work users wait for before introducing caching or optimization complexity.

Large client bundles, unnecessary hydration, and avoidable client components are identified.

Images have appropriate dimensions, formats, loading priority, and responsive sizes.

Database queries return only required fields and avoid repeated work in lists or loops.

Caching, revalidation, and dynamic rendering decisions match how often data changes.

Third-party scripts load only where they provide value and after consent when required.

6

Security and privacy

Protect authentication, data, integrations, and public forms using proportional controls.

Authentication and authorization are enforced on the server for every protected action.

Inputs are validated, normalized, length-limited, and safely rendered or stored.

Secrets remain server-side and sensitive settings are encrypted where appropriate.

Public forms use origin checks, rate limits, abuse controls, and privacy-conscious logging.

Personal data collection, retention, analytics consent, and deletion responsibilities are documented.

7

Data and integrations

Make failure, ownership, and recovery explicit wherever the product depends on another system.

Schema constraints, indexes, relationships, and lifecycle states match real workflows.

Migrations and seeds are repeatable, guarded, and safe for their intended environment.

External requests define timeouts, retries, idempotency, validation, and failure behavior.

Webhooks and asynchronous work can be retried without creating duplicate effects.

Integration credentials, ownership, support contacts, and environment differences are documented.

8

Delivery and operations

Ensure changes can be validated, released, observed, and recovered without relying on one persons memory.

Lint, type, schema, seed, build, and critical workflow checks run at appropriate stages.

CI avoids duplicate or unnecessarily expensive runs through path, branch, and concurrency controls.

Deployment requirements, environment variables, health checks, and rollback paths are documented.

Logs contain useful request and entity context without exposing private content or secrets.

Production incidents, backups, restore checks, and recurring maintenance have clear ownership.

9

Prioritization and execution

Turn findings into a small sequence of measurable changes rather than one oversized rewrite.

Each finding states the evidence, user or business impact, risk, and affected system.

Work is ranked by impact, urgency, effort, reversibility, and dependency order.

The first milestone fixes correctness, trust, and lead or revenue loss before cosmetic work.

Commits and pull requests remain focused, independently understandable, and easy to validate.

Every improvement has a validation method and a clear definition of done.