FediScanner

#react

← Back

Hello DEV Community! 👋

I'm Ali Raza, a Software Architect and Engineer, and the founder of OsmicSoft.

I've always enjoyed exploring new technologies, designing software architectures, and solving complex engineering problems. Recently, I've been focusing on something I've wanted to do for a long time: building my own SaaS products from the ground up.

Rather than just developing applications, I want to build products that solve real business problems, are scalable, secure, maintainable, and capable of growing with their users.

In this article, I'll share what I'm building, the technologies I'm using, the architecture I'm planning, and some of the technical challenges and decisions involved in developing a SaaS platform.

🚀 The Idea Behind My SaaS


My goal with OsmicSoft is to develop practical software solutions that help businesses manage their daily operations more efficiently.

I'm particularly interested in SaaS applications because they present interesting engineering challenges, including:

  • Multi-tenant architecture
  • Scalable backend APIs
  • Secure authentication and authorisation
  • Subscription and billing management
  • Efficient database design
  • Application performance and reliability
  • Maintainable and modular codebases

I'm currently working on business management and HR software, with the aim of building products that can serve different businesses without requiring a separate application for every customer.

🛠️ The Technology Stack


One of the first decisions when starting a SaaS project is selecting the right technology stack.

I wanted a stack that would allow me to develop quickly, maintain clean architecture, support future growth, and make it possible to introduce mobile applications later.

Here's the stack I'm using:

TechnologyPurposeRuby on RailsBackend APIs and business logicNext.jsPublic website, pricing, onboarding and subscription workflowsReact + ViteMain application interfacePostgreSQLRelational databaseTailwind CSSUI stylingDockerApplication containerisationLinuxServer environmentStripeSubscription payments

1. Ruby on Rails for the Backend


I'm using Ruby on Rails to build the backend as a dedicated API service.

I chose this approach to keep business logic, authentication, authorisation, subscription management and database operations separate from the frontend.

Some of the key architectural goals are:

  • RESTful APIs with consistent response structures.
  • Centralised business logic and validation.
  • Secure authentication and role-based access control.
  • Modular services for different business domains.
  • API versioning to support future integrations.
  • Background processing for asynchronous tasks.

One of my main considerations is keeping the backend independent of the frontend.

This means that in the future, I should be able to build mobile applications or integrate third-party services without having to rewrite the core business logic.

2. Next.js for the Public Website


I'm using Next.js for the public-facing part of the platform.

This includes:

  • Marketing and product pages.
  • Pricing and subscription plans.
  • Customer registration and onboarding.
  • Subscription checkout.
  • Public documentation and other informational pages.

I want to keep these responsibilities separate from the main application interface.

This separation makes it easier to manage public-facing content, onboarding workflows and the core application independently.

3. React and Vite for the Application


For the main application interface, I'm using React with Vite.

The application is intended to provide a clean and responsive experience for business owners, administrators, HR teams and employees.

Some of the key interface considerations include:

  • Reusable components.
  • Modular feature-based organisation.
  • Role-aware navigation and permissions.
  • Responsive layouts.
  • Efficient API integration.
  • Consistent design patterns.

I also want the application to be straightforward for new users. A powerful application is not particularly useful if customers struggle to understand how to use it.

That's why I'm considering guided onboarding, contextual help and clear explanations for complex features.

🏗️ Designing a Multi-Tenant SaaS Architecture


One of the most interesting parts of building this platform is designing its multi-tenant architecture.

In a traditional application, each customer might have a completely separate installation. In a multi-tenant SaaS application, multiple organisations can use the same platform while their data and permissions remain isolated.

For example:

  • company1.example.com
  • company2.example.com
  • company3.example.com

Each organisation should have access to its own employees, records, settings, subscriptions and business information.

The backend must enforce tenant isolation rather than relying only on frontend restrictions.

Some of the areas I'm considering include:

  • Tenant identification and subdomain resolution.
  • Organisation-level permissions and access control.
  • Database query scoping and data isolation.
  • Tenant-aware background jobs.
  • Organisation-specific configuration.
  • Secure handling of cross-tenant requests.

Public Website
Next.js
|
v
Subscription & Onboarding
|
v
Rails API Backend
|
+------------+------------+
| | |
v v v
Tenant A Tenant B Tenant C
| | |
+------------+------------+
|
v
PostgreSQL

`

This is a conceptual view of the architecture, not a claim that every component is already implemented.

The main principle is to keep tenant-specific access controlled and verified on the backend, with appropriate database constraints, authorisation checks and automated tests.

🔐 Security Is Not an Afterthought


Security is one of the areas I want to prioritise from the beginning.

A SaaS platform may handle sensitive business information, employee records and financial data. That makes security an essential part of the architecture.

Some of the areas I'm focusing on include:

  • Authentication and secure session management.
  • Role-based and organisation-level permissions.
  • Protection against SQL injection and common web vulnerabilities.
  • API rate limiting and abuse prevention.
  • Secure password handling.
  • Input validation and sanitisation.
  • Audit logging for important operations.
  • HTTPS and secure configuration management.
  • Database backups and recovery planning.

For multi-tenant systems in particular, preventing unauthorised access to another organisation's information is critical.

I want to incorporate automated tests for tenant isolation and authorisation so that future changes don't accidentally introduce security vulnerabilities.

💳 Building a Flexible Subscription Model


Another important part of the platform is subscription management.

Rather than relying entirely on fixed packages, I'm exploring a flexible pricing model based on the number of employees, with optional paid features.

For example, a business could subscribe according to its workforce size and enable additional modules depending on its requirements.

The subscription architecture needs to support:

  • Recurring billing.
  • Employee-based pricing.
  • Optional paid modules.
  • Subscription upgrades and downgrades.
  • Payment failures and subscription status changes.
  • Billing history and invoices.
  • Webhook processing and payment reconciliation.

I'm using Stripe as the planned payment provider.

One important engineering consideration is ensuring that subscription status and payment events are processed reliably, including handling duplicate webhook events and temporary payment failures.

📦 Containerisation and Deployment


I'm also using Docker to make the development and deployment environments more consistent.

The intention is to keep the different application components independently deployable.

For example:

text
Application Infrastructure
│
├── Public Web
│ └── Next.js
│
├── Main Application
│ └── React + Vite
│
├── Backend
│ ├── Rails API
│ └── Background Worker
│
├── Database
│ └── PostgreSQL
│
└── Infrastructure
 ├── Reverse Proxy
 ├── SSL
 ├── Monitoring
 └── Backups

This structure provides a foundation for managing the different services and scaling them independently when required.

I'm also considering deployment automation, logging, health checks, database migrations, backup verification and monitoring as part of the platform's operational design.

🧩 Modular Features and Future Expansion


I want to avoid building a tightly coupled application where every feature depends directly on every other feature.

Instead, I'm aiming for a modular architecture with clearly defined business domains.

Potential modules include:

  • Employee management
  • Attendance and leave management
  • Payroll integrations
  • Document management
  • Onboarding and offboarding
  • Reporting and analytics
  • Subscription and billing management

The intention is to allow organisations to use the features relevant to their needs while keeping the underlying platform maintainable.

This also creates opportunities to expand the product over time without requiring a complete architectural rewrite.

🤔 Some Challenges I'm Thinking About


Building a SaaS platform involves much more than writing code. Some of the key engineering and product challenges I'm working through include:

1. Balancing simplicity and scalability

It's tempting to introduce complex infrastructure early, but unnecessary complexity can slow development and increase maintenance costs. I want to build an architecture that meets current needs while allowing sensible future growth.

2. Keeping tenant data isolated

Multi-tenancy introduces additional security and testing requirements. Tenant identification, permissions and database access need to be designed carefully.

3. Making onboarding intuitive

New users shouldn't need extensive technical knowledge to get started. I'm exploring guided workflows, contextual explanations and interactive onboarding.

4. Designing for future integrations

An API-first backend should make it easier to support mobile applications, third-party integrations and external services.

5. Managing infrastructure costs

For an early-stage SaaS business, infrastructure should be reliable without introducing unnecessary operational expenses. I'm considering how to optimise resource usage while maintaining appropriate security and availability.

6. Building something customers actually need

Perhaps the most important challenge isn't technical at all. It's understanding real customer problems, validating product assumptions and prioritising features that deliver meaningful value.

🌱 What I Want to Learn and Share


As I continue developing these products, I want to share practical engineering experiences with the DEV Community.

Some topics I plan to explore include:

  • Building and securing multi-tenant SaaS applications.
  • Ruby on Rails API architecture.
  • Integrating Next.js and React applications with Rails.
  • Designing scalable database structures.
  • Docker-based deployment workflows.
  • SaaS subscription and billing architecture.
  • Application security and performance.
  • Lessons from launching and maintaining software products.

I also hope to contribute to open-source projects and learn from developers who have tackled similar engineering challenges.

🎯 My Long-Term Goal


My long-term goal is to grow OsmicSoft into a software company that develops useful, reliable and scalable products.

I want to focus on solving genuine business problems, building sustainable software and continuously improving my engineering practices.

I'm still learning, experimenting and refining my approach. I don't expect every architectural decision to be perfect from the beginning, but I believe documenting the process, evaluating trade-offs and learning from mistakes are important parts of becoming a better engineer.

💬 Let's Connect


I'd love to hear from other developers, software architects, SaaS founders and engineers.

A few questions for the community:

  1. What technology stack do you prefer for building SaaS applications, and why?
  2. What challenges have you encountered when implementing multi-tenant architecture?
  3. What would you recommend to someone building and launching their own SaaS product?
  4. How do you balance scalability, security and infrastructure costs in an early-stage product?

Feel free to share your experiences, suggestions or constructive feedback. I'm looking forward to learning from the community and sharing more as the project progresses.

Let's build, learn and grow together! 🚀

About me: I'm Ali Raza, a Software Architect and Engineer, and the founder of OsmicSoft. I'm interested in software architecture, SaaS engineering, backend development, cloud infrastructure and emerging technologies.

DEVCommunity #SaaS #SoftwareArchitecture #RubyOnRails #NextJS #React #WebDevelopment #MultiTenant #Docker #SoftwareEngineering

#architecture #saas #softwaredevelopment #startup #software #coding #development #engineering #inclusive #community
# Building My Own SaaS Platform: Architecture, Technology Choices, and Lessons Along the Way 🚀

Show Original PostReport

Introduction


Large Ant Design (AntD) forms can go from snappy to janky fast. I introduced React Hook Form (RHF) expecting a speed boost — but saw the whole form commit on every keystroke and 400–500ms Profiler flamecharts. The problem wasn’t React: it was patterns that accidentally subscribed the entire tree.

This article shows measurement-first fixes that keep re-renders local, preserve RHF’s uncontrolled performance model, and scale to hundreds of rows. Keyword: react-hook-form antd performance.

Why forms get slow


React Hook Form is fast because it keeps values out of React state (uncontrolled). But performance collapses when you accidentally subscribe at the wrong level. Common causes:

  • Calling watch() at the form root (it subscribes and re-renders the caller).
  • Using uncontrolled/controlled switches (undefined default value) and heavy validation on every keystroke.
  • Wrapping AntD controlled inputs directly in parent components so a sibling change rerenders everyone.
  • Using index keys in useFieldArray (breaks on reorder and virtualization).
  • Recreating resolvers/schema or defaultValues each render.

Measure first with React Profiler: which component commits on typing? Narrow the blast radius by ensuring "where you read = where it re-renders."

Five surgical fixes


Below are five focused changes that cut re-renders and returned sub‑50ms interactions on a 200-row table in my case.

1) Move watchers to the leaf (useWatch)


Rule: if you only display or compute a derived value for one cell, call useWatch in that cell component — not watch() at the root.

Bad:

// inside the top-level form
const values = watch(); // re-renders top-level on every change

Good:

// PriceCell.tsx
import { useWatch, Control } from 'react-hook-form';

function PriceCell({ control, name }: { control: Control<any>; name: string }) {
const price = useWatch({ control, name });
return <div>{price}</div>;
}

Moving a price watcher from the root into PriceCell reduced renders from dozens to one per cell in my test.

2) Wrap AntD controlled inputs with a tiny adapter (useController)


AntD inputs are controlled; directly rendering them inside the parent makes the parent re-render on sibling changes. Use useController (or Controller) locally to isolate subscriptions.

Example adapter for Select (TypeScript):

import React from 'react';
import { useController, Control } from 'react-hook-form';
import { Select } from 'antd';

type RHFAntdSelectProps = { name: string; control: Control<any>; options: { label: string; value: any }[] };

export const RHFSelect: React.FC<RHFAntdSelectProps> = React.memo(function RHFSelect({ name, control, options }) {
const { field } = useController({ name, control });
return <Select value={field.value} onChange={(v) => field.onChange(v)} options={options} />;
});

Because useController subscribes only to that field, parent and siblings stop re-rendering when this input changes.

3) Memoize nested inputs and compare only the props that matter


Wrap expensive field components with React.memo and provide a stable props surface. Only pass primitives or stable refs. When comparing, only care about value, error, and isDirty.

Example:

const Cell = React.memo(function Cell({ value, error, onChange }: CellProps) {
// render heavy cell
});

// Pass value and error, not the whole form object

Avoid passing inline functions or newly created objects as props unless they’re memoized (useCallback/useMemo).

4) Virtualize field arrays and use stable field.id keys


For hundreds of rows, render only visible rows with a virtualizer (e.g., @tanstack/react-virtual). Always use the stable field.id from useFieldArray as key — never index.

Short virtualization sketch:

import { useVirtualizer } from '@tanstack/react-virtual';
import { useFieldArray, useForm } from 'react-hook-form';

function VirtualizedRows() {
const { control, register } = useForm({ defaultValues: { rows: [] } });
const { fields } = useFieldArray({ control, name: 'rows' });
const parentRef = React.useRef<HTMLDivElement | null>(null);
const virtualizer = useVirtualizer({
count: fields.length,
getScrollElement: () => parentRef.current,
estimateSize: () => 56,
});

return (
<div ref={parentRef} style={{ height: 600, overflow: 'auto' }}>
<div style={{ height: virtualizer.getTotalSize(), position: 'relative' }}>
{virtualizer.getVirtualItems().map((v) => {
const index = v.index;
const field = fields[index];
return (
<div key={field.id} style={{ position: 'absolute', transform: `translateY(${v.start}px)` }}>
<input {...register(`rows.${index}.name`)} />
</div>
);
})}
</div>
</div>
);
}

Virtualization + field.id keeps the DOM light while RHF keeps values in memory.

5) Provide stable defaultValues and use a memoized resolver (zodResolver)


Unstable defaultValues or a fresh resolver/schema every render causes controlled/uncontrolled churn and extra validation work. Define schema and defaultValues outside the component (or memoize) and prefer onTouched validation.

Bad:

function Form() {
const schema = z.object({ /* defined inline */ }); // recreated every render
const form = useForm({ resolver: zodResolver(schema), defaultValues: fetchDefault() });
}

Good:

const invoiceSchema = z.object({ items: z.array(z.object({ name: z.string(), price: z.number() })) });
const initialDefaults = { items: [{ name: '', price: 0 }] } as const;

function Form() {
const form = useForm({ resolver: zodResolver(invoiceSchema), defaultValues: initialDefaults, mode: 'onTouched' });
}

Use mode: 'onTouched' or 'onSubmit' as a default; only use 'onChange' where immediate validation is truly needed.

Putting it together: a concrete win


In my form, a Price column was being watched at the form root to compute totals. Moving that watch into a small PriceCell via useWatch turned dozens of renders into one per cell. Profiler showed dramatically fewer commits and narrow flame widths. On a 200-row form interactions dropped from 400–500ms commits to under 50ms.

Practical checklist


  • Profile first: open React Profiler and record a keystroke. Find the component that re-renders.
  • Replace watch() at the root with useWatch in leaves.
  • Wrap AntD controlled components with useController adapters and React.memo.
  • Virtualize long lists with @tanstack/react-virtual and key by field.id.
  • Move schema and defaultValues out of render; use a memoized zodResolver.
  • Prefer onTouched/onSubmit validation; trigger specific fields manually when necessary.


Conclusion


Don’t rewrite the UI — fix the patterns. RHF gives you the performance potential; the job is to keep subscriptions tiny and stable. A few surgical moves (useWatch at the leaf, small useController adapters, memoization, virtualization, and stable resolver/defaults) will usually turn a janky AntD form into an instant-feeling editor.

If you want, I can paste the tiny adapter components and the full virtualized useFieldArray sample I used in production.

Further reading


  • React Hook Form docs: useController, useWatch, useFieldArray
  • @tanstack/react-virtual docs
  • zod + @hookform/resolvers examples

What’s the biggest performance surprise you’ve found in a form at scale?#react #typescript #performance #forms #software #coding #development #engineering #inclusive #community
Speed up AntD forms with React Hook Form & TypeScript

Show Original PostReport

Still safe touring "Keep it safe" in Czechia, two more shows in Prag for the wonderful festival Feet Forward, before going back to Sweden with some "Just Stop".

For any more information and future performances, go on our website or write us. https://reactperformances.com

#reactperformances #publicspace #performance #react #sweden #streetperformance #sitespecific #insitu #dance #dans #skane #sweden #schooltour #salto #feetforwardfestival #prag #czechrepublic #keepitsafe #yellowvest #keepitsafe #safetyfirst #nopanic #cones #rope #donttouchtherope #safety #safe #youngaudience #youthperformance #bus #busstop #road #juststop #oskarshamn #rostanga #svalov

Show Original PostReport

We've had such nice time at the MOVE Fest in Ostrava!
A special thank you to Anna, who helped us with the translation of the performance, and to Tereza, who was our personal assistent / a local guide during our stay - it was a pleasure meeting you!
And always remember: nedotýkej se lana!

#Ostrava#MoveFest#reactperformances #publicspace #performance #react #sweden #streetperformance #sitespecific #insitu #dance #dans#yellowvest #keepitsafe #safetyfirst #nopanic #cones #rope #donttouchtherope #safety #safe

Show Original PostReport