Technology changes constantly. New frameworks appear every year, tools become obsolete, and trends come and go. But after working on real production systems for startups, e‑commerce platforms, internal tools, and AI‑driven services, I've learned that what truly matters is not novelty, but reliability.
My current stack is the result of years of iteration, mistakes, refactors, and systems running under real business constraints. It is not designed to look impressive on a landing page. It is designed to survive growth, changing requirements, new developers joining the project, and the unavoidable complexity that comes with any serious SaaS product.
This article explains how and why I structure my technical stack the way I do today.
Choosing boring technology on purpose
When you build SaaS products long enough, you start valuing predictability over excitement.
Early in my career, I experimented a lot: different frameworks, exotic databases, new paradigms, unproven tools. Some worked. Many created unnecessary friction later: difficult upgrades, lack of documentation, limited hiring pool, or subtle production bugs that were hard to diagnose.
Today, I deliberately choose technologies that are:
- well understood
- widely adopted
- boring in production
- easy to debug
- easy to recruit for
- supported for years
This does not slow projects down. It accelerates them in the long run.
Backend: stability first, flexibility second
On the backend side, most of my SaaS projects rely on Node.js with TypeScript.
Not because it is trendy, but because it provides an excellent balance between development speed, ecosystem maturity, and long‑term maintainability.
TypeScript alone has changed how I build systems. It turns large codebases into something that can be reasoned about. It makes refactoring safer. It forces clarity in data models and API contracts. And when several developers collaborate on the same backend, it becomes a form of living documentation.
For APIs, I usually build classic REST services using Express or Fastify. I prefer explicit endpoints and clear contracts over overly abstract architectures. When systems grow, simplicity becomes a form of scalability.
For data access, I rely heavily on Prisma. It provides strong typing, readable schemas, safe migrations, and a good balance between abstraction and control. The underlying database is most often PostgreSQL, sometimes MySQL depending on the project's history or hosting constraints.
Redis is frequently added when the product grows: for caching, background jobs, queues, rate limiting, or session‑like shared state. It is simple, fast, and extremely reliable when used properly.
This backend stack allows me to design systems that are easy to extend, easy to debug, and easy to operate.
Frontend: clarity over cleverness
On the frontend, I work primarily with React and TypeScript.
Here again, the choice is pragmatic. React is not perfect, but its ecosystem is massive, stable, and well understood. When a client wants to hire additional developers later, finding React engineers is trivial. That alone matters a lot for long‑term projects.
TypeScript on the frontend provides the same benefits as on the backend: fewer runtime errors, safer refactors, and clearer component interfaces.
For styling and UI structure, I usually rely on Tailwind and shadcn/ui. They allow me to build consistent interfaces quickly without introducing heavy design systems or complex CSS architectures that become difficult to maintain.
In SaaS dashboards, internal tools, and admin panels, visual simplicity beats complexity. What matters is that the UI stays predictable, fast, and understandable even as features accumulate.
I pay particular attention to:
- API‑driven components
- clear separation between UI and business logic
- predictable state flows
- lazy loading and code splitting when relevant
- consistent design patterns
These details rarely appear in marketing screenshots, but they determine whether the frontend remains manageable two years later.
Infrastructure: reproducibility over heroics
Infrastructure is where many SaaS projects silently fail.
Not because servers are slow, but because deployments become stressful, environments drift apart, and nobody is entirely sure how the system is actually running.
For this reason, everything I build runs in Docker.
Development, staging, production: the same containers, the same configuration structure, the same startup process. This drastically reduces the "it works on my machine" problem and makes onboarding new developers much easier.
For deployments, I rely on CI/CD pipelines that build, test, and deploy automatically. Whether it is GitHub Actions, Coolify, or custom pipelines, the principle remains the same: human intervention should be minimal.
Depending on the project, I use classic cloud providers or self‑hosted infrastructure. In some SaaS products, cloud simplicity is perfect. In others, cost control, data privacy, or GPU usage makes self‑hosting more sensible.
The important part is not where the servers run, but that:
- deployments are reproducible
- rollbacks are possible
- environments are isolated
- configuration is externalized
- secrets are managed properly
If deployment feels dangerous, something is wrong.
Why this stack works well for SaaS
This stack is not optimized for demo projects or short‑lived experiments. It is optimized for products that must survive real usage.
It scales well technically, but more importantly, it scales organizationally:
- new developers can understand the codebase quickly
- bugs can be diagnosed without guesswork
- features can be added without fear
- infrastructure can grow gradually
I've used variations of this stack for:
- multi‑store e‑commerce platforms
- logistics and warehouse automation systems
- Shopify administration tools
- AI‑powered SaaS services
- internal company dashboards
- financial and analytics platforms
In all these cases, the technical choices faded into the background, which is exactly what you want. The product becomes the focus, not the technology.
Adapting to existing ecosystems
Of course, not every project starts from scratch.
Many clients already have an existing codebase, different databases, or specific infrastructure constraints. In those cases, I adapt.
I am comfortable working with other frameworks, ORMs, cloud providers, or deployment models. What matters to me is not enforcing my favorite tools, but maintaining the same principles: clarity, safety, reproducibility, and long‑term maintainability.
A stack shaped by production, not trends
Every major technical decision in this stack comes from real problems I encountered in production:
- systems that were impossible to debug
- databases that became bottlenecks
- frontends that no one dared to touch anymore
- deployments that broke randomly
- products blocked by early shortcuts
Each failure refined the way I work today.
My goal is simple: build systems that become boring to operate.
When nobody is afraid of deploying on Friday afternoon, when adding a feature does not require touching ten unrelated modules, when logs clearly explain what went wrong, then the stack is doing its job.
Working with this stack
If you are building a SaaS product, an internal platform, or a technical startup and you care about long‑term stability as much as short‑term speed, this is the type of environment I usually work with.
I collaborate with clients in France and internationally as a freelance full‑stack developer, often acting as both senior engineer and technical lead, helping design systems meant to last rather than prototypes meant to be thrown away.
If that mindset resonates with your project, this stack will probably fit it too.