Architecture

Enterprise SaaS in Rails does not start with microservices

How a modular monolith, explicit organization context and transactional audit create a dependable SaaS foundation.

Enterprise SaaS does not start with microservices, Kubernetes or a dozen repositories. It starts with clear responsibility boundaries, organization isolation, consistent authorization and a history the business can trust.

Rails fits that work well. Its simplicity keeps business decisions close to the code, but simplicity is not a substitute for discipline. Once an application serves multiple organizations, roles, background processes and critical decisions, framework conventions alone are no longer an architecture.

Start with the right boundaries

A modular monolith gives the team one deployment path and one database transaction while still separating a stable platform from a changing domain.

The platform can share:

  • identity and authentication,
  • organizations, memberships and roles,
  • files and controlled access,
  • the audit log,
  • request and job context,
  • common privacy rules.

Each business module keeps its own models, commands, policies, events and process rules. A future module can reuse mature platform capabilities without pretending its workflow has the same meaning as the domain operating today.

Context is part of the operation

A critical command needs more than the record it changes. It also needs an actor, organization, role and invocation source. The same use case may be called from a controller, background job, import or administration tool.

Request / Job
      ↓
Actor + Organization + Role
      ↓
Policy + Business Command
      ↓
Business State + Audit Event
      ↓
One PostgreSQL Transaction

The controller handles HTTP, the policy protects the endpoint and query scope, and the command enforces the use-case invariants. Hiding a button is useful UX; it is not a security boundary.

Audit belongs in the transaction

For a critical operation, the state change and its audit event should be persisted together. If the audit record cannot be stored, the business change should not commit either.

An event needs a stable type, public identifier, actor, organization, source and correlation with the originating request or job. Metadata should follow a narrow contract: no passwords, tokens, documents or unrestricted request parameters.

Rails model protection is not enough on its own. The application process should not own the audit tables or run as a database superuser. Runtime may append events, but it should not be able to update, delete or disable their protection.

DRY means shared meaning

Two pieces of code do not form a useful abstraction merely because they look similar. Share a stable mechanism - recording events, checking membership, propagating correlation IDs - rather than forcing different business decisions into one universal engine.

KISS does not mean “the fewest classes” either. It means the simplest design that preserves the required guarantees and remains understandable to the next team.

What an enterprise foundation really provides

Code can provide tenant isolation, event integrity, access control and observability. It does not provide compliance automatically. Retention policies, emergency procedures, restore testing, credential rotation and sometimes an external trust boundary are operational and legal decisions.

Rails remains a strong choice for serious SaaS systems. The central advantage of a modular monolith is not simply avoiding microservices. It is keeping business rules, transactions and responsibility in one place that the team can still reason about.

Read more about our production technology standards and modernization and infrastructure rescue. If you are shaping a similar system, start a conversation.

Related services

Services connected to this article.

ModernizationModernize Rails systems while production keeps running.

Rails upgrades, React/Vite migrations, PostgreSQL tuning, Linux production systems, NGINX, SSL, Puma, background workers, queues and deployment flows.