<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Sanket Jagtap</title>
    <description>The latest articles on DEV Community by Sanket Jagtap (@sanketjagtap1).</description>
    <link>https://dev.to/sanketjagtap1</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4056696%2F8eeb8804-a896-4744-89cd-362011d69e45.png</url>
      <title>DEV Community: Sanket Jagtap</title>
      <link>https://dev.to/sanketjagtap1</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sanketjagtap1"/>
    <language>en</language>
    <item>
      <title>Deploying a Full-Stack App with Docker and Nginx on a VPS</title>
      <dc:creator>Sanket Jagtap</dc:creator>
      <pubDate>Mon, 22 Jun 2026 16:57:25 +0000</pubDate>
      <link>https://dev.to/sanketjagtap1/deploying-a-full-stack-app-with-docker-and-nginx-on-a-vps-1710</link>
      <guid>https://dev.to/sanketjagtap1/deploying-a-full-stack-app-with-docker-and-nginx-on-a-vps-1710</guid>
      <description>&lt;p&gt;You do not need Kubernetes to ship a real app. A single VPS with Nginx and Docker handles a surprising amount of traffic. Here is the setup that runs this portfolio.&lt;/p&gt;

&lt;h2&gt;
  
  
  The topology
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Nginx is the front door, terminating SSL and serving the built Angular app as static files.&lt;/li&gt;
&lt;li&gt;The Node + Prisma API runs in a Docker container on a private port (6000).&lt;/li&gt;
&lt;li&gt;MySQL is the database; uploaded images live on a persistent host volume.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Nginx as the front door
&lt;/h2&gt;

&lt;p&gt;One server block does three jobs: serve the SPA with a history-API fallback, reverse-proxy the API, and serve uploaded files. The detail that bites everyone is the &lt;strong&gt;trailing slash on proxy_pass&lt;/strong&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/api/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://localhost:6000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;# no trailing slash -&amp;gt; keeps /api prefix&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kn"&gt;try_files&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt;&lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="n"&gt;/index.html&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;# SPA fallback&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With a trailing slash Nginx strips the matched prefix, so /api/users would arrive at the backend as /users and 404. Dropping the slash preserves the path.&lt;/p&gt;

&lt;h2&gt;
  
  
  Persistent uploads
&lt;/h2&gt;

&lt;p&gt;Anything written inside a container is gone on the next deploy. Uploads must live on the host and be mounted in, with ownership that matches the container user:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--restart&lt;/span&gt; unless-stopped &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; 6000:6000 &lt;span class="nt"&gt;--env-file&lt;/span&gt; .env &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; /opt/app/uploads:/opt/app/uploads &lt;span class="se"&gt;\&lt;/span&gt;
  portfolio
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  SSL
&lt;/h2&gt;

&lt;p&gt;Let's Encrypt via certbot gives free, auto-renewing certificates. Nginx redirects all HTTP to HTTPS, so the app is TLS-only.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deploys
&lt;/h2&gt;

&lt;p&gt;The flow is pleasantly boring: pull the latest code, &lt;strong&gt;docker build&lt;/strong&gt; , stop the old container, run the new one. Because migrations run on startup and uploads live outside the container, a redeploy is safe and repeatable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gotchas worth remembering
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;proxy_pass trailing slash changes the forwarded path — choose deliberately.&lt;/li&gt;
&lt;li&gt;A non-root container user cannot write to a root-owned host volume; fix the ownership.&lt;/li&gt;
&lt;li&gt;An existing database needs its migrations baselined once (P3005) before migrate deploy will run.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>docker</category>
      <category>nginx</category>
      <category>devops</category>
      <category>deployment</category>
    </item>
    <item>
      <title>Making a Node.js and Prisma API Production-Ready</title>
      <dc:creator>Sanket Jagtap</dc:creator>
      <pubDate>Mon, 22 Jun 2026 16:57:25 +0000</pubDate>
      <link>https://dev.to/sanketjagtap1/making-a-nodejs-and-prisma-api-production-ready-5gh8</link>
      <guid>https://dev.to/sanketjagtap1/making-a-nodejs-and-prisma-api-production-ready-5gh8</guid>
      <description>&lt;p&gt;"It works on my machine" and "it is production-ready" are very different statements. Here is the checklist I worked through to take an Express + Prisma + MySQL API from the first to the second — using this very portfolio backend as the guinea pig.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Real migrations, not db push
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;prisma db push&lt;/strong&gt; is great for prototyping and dangerous in production — there is no history and no safe rollback. The fix is committed migrations applied on deploy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx prisma migrate dev &lt;span class="nt"&gt;--name&lt;/span&gt; init &lt;span class="c"&gt;# generate + commit&lt;/span&gt;
npx prisma migrate deploy &lt;span class="c"&gt;# run on startup (never prompts)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the database already has tables but no migration history you will hit &lt;strong&gt;P3005&lt;/strong&gt;. Baseline it once by marking the migration as already applied, then deploys are clean forever after.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Graceful shutdown
&lt;/h2&gt;

&lt;p&gt;Containers get SIGTERM on every redeploy. Without handling it you drop in-flight requests and leak database connections. Close the server, then disconnect Prisma:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SIGTERM&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;prisma&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;$disconnect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Map errors to real status codes
&lt;/h2&gt;

&lt;p&gt;A blanket 500 tells the client nothing. A small helper maps known Prisma errors — unique violation to &lt;strong&gt;409&lt;/strong&gt; , record-not-found to &lt;strong&gt;404&lt;/strong&gt; — and keeps the raw error server-side only.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Liveness vs readiness
&lt;/h2&gt;

&lt;p&gt;Two different questions. &lt;strong&gt;/health&lt;/strong&gt; answers "is the process up?" cheaply. &lt;strong&gt;/health/ready&lt;/strong&gt; answers "can I serve traffic?" by actually pinging the database with SELECT 1 — that is what your load balancer should probe.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Config and secrets
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Fail fast at startup if a required secret like JWT_SECRET is missing.&lt;/li&gt;
&lt;li&gt;Never ship a hardcoded admin password — seed a random one and print it once.&lt;/li&gt;
&lt;li&gt;Keep .env out of git; commit a .env.example template instead.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  6. A lean Docker image
&lt;/h2&gt;

&lt;p&gt;A multi-stage build compiles TypeScript in a builder stage and ships only the runtime deps and compiled output, running as a non-root user. Migrations run as the first thing the container does on boot.&lt;/p&gt;

&lt;p&gt;None of this is exciting, and that is the point. Production-ready means boring, predictable and observable.&lt;/p&gt;

</description>
      <category>node</category>
      <category>express</category>
      <category>prisma</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Inside AlgoETF: An Algorithmic ETF Trading Platform</title>
      <dc:creator>Sanket Jagtap</dc:creator>
      <pubDate>Mon, 22 Jun 2026 16:57:25 +0000</pubDate>
      <link>https://dev.to/sanketjagtap1/inside-algoetf-an-algorithmic-etf-trading-platform-3ep7</link>
      <guid>https://dev.to/sanketjagtap1/inside-algoetf-an-algorithmic-etf-trading-platform-3ep7</guid>
      <description>&lt;p&gt;AlgoETF is an algorithmic trading platform for Indian ETFs. It runs rule-based strategies against live market data, places orders through connected brokers, and lets you research everything with a built-in backtester before risking real money.&lt;/p&gt;

&lt;h2&gt;
  
  
  The core strategy
&lt;/h2&gt;

&lt;p&gt;At its heart is a simple, explainable idea: &lt;strong&gt;buy the dip, sell the rise&lt;/strong&gt; , gated by momentum. The engine watches each ETF and acts when price moves a configured percentage, but only when the &lt;strong&gt;RSI(14)&lt;/strong&gt; filter agrees — so it avoids buying into a falling knife or selling into strength.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Buy on dip and sell on rise thresholds, per ETF.&lt;/li&gt;
&lt;li&gt;RSI oversold / overbought gate to filter bad entries.&lt;/li&gt;
&lt;li&gt;Cycle targets so each position has a defined exit.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Real-time architecture
&lt;/h2&gt;

&lt;p&gt;The frontend is Angular; the backend is Node.js + Express. Live prices and order updates stream over &lt;strong&gt;WebSockets&lt;/strong&gt; , &lt;strong&gt;Redis&lt;/strong&gt; handles pub/sub and hot state, and &lt;strong&gt;MySQL&lt;/strong&gt; is the system of record for strategies, cycles and orders. Broker APIs sit behind an adapter layer so new brokers can be added without touching the strategy code.&lt;/p&gt;

&lt;h2&gt;
  
  
  The backtester
&lt;/h2&gt;

&lt;p&gt;You can replay historical 1-minute data through the exact same strategy logic — research only, no orders placed. The best part is the &lt;strong&gt;A/B improvement rules&lt;/strong&gt; : toggle a stop-loss, cap averaging, an EMA trend filter, a volume filter or a trailing exit, and compare the result against the base strategy.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Parameters: stock, date range, buy dip %, sell rise %
Gate: RSI period, oversold &amp;lt;, overbought &amp;gt;
Risk: qty/order, start capital, brokerage %, slippage %
A/B rules: stop loss, cap averaging, EMA filter, trailing exit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Safety first
&lt;/h2&gt;

&lt;p&gt;Trading code is unforgiving, so the platform separates &lt;strong&gt;live&lt;/strong&gt; , &lt;strong&gt;paper&lt;/strong&gt; and &lt;strong&gt;backtest&lt;/strong&gt; modes explicitly. Paper trading mirrors live behaviour with no money at stake, and every order is logged with a clear success / pending / failed status.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lessons learned
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Make strategies boring and explainable — you have to trust them with money.&lt;/li&gt;
&lt;li&gt;Backtesting and live execution must share the same code path, or your results lie.&lt;/li&gt;
&lt;li&gt;An audit trail of every order is not optional in fintech.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>angular</category>
      <category>node</category>
      <category>trading</category>
      <category>websockets</category>
    </item>
    <item>
      <title>Building BeatNest: A Cross-Platform Music App in Flutter</title>
      <dc:creator>Sanket Jagtap</dc:creator>
      <pubDate>Mon, 22 Jun 2026 16:57:25 +0000</pubDate>
      <link>https://dev.to/sanketjagtap1/building-beatnest-a-cross-platform-music-app-in-flutter-4ei</link>
      <guid>https://dev.to/sanketjagtap1/building-beatnest-a-cross-platform-music-app-in-flutter-4ei</guid>
      <description>&lt;p&gt;BeatNest is a cross-platform music streaming app built with Flutter. It streams tracks from the Saavn API and focuses on the things that actually make a music player feel good: &lt;strong&gt;gapless background playback&lt;/strong&gt; , media-style notifications, lock-screen controls and offline listening.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Flutter
&lt;/h2&gt;

&lt;p&gt;One codebase, two stores. Flutter let me ship a consistent UI on Android and iOS while still dropping down to native APIs where it mattered — the media session, notifications and storage permissions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture
&lt;/h2&gt;

&lt;p&gt;The app follows a clean, service-oriented structure so the UI stays dumb and the logic stays testable:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;ApiService&lt;/strong&gt; — talks to the Saavn API for search and trending songs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MusicService&lt;/strong&gt; — the playback brain: queue, current track, play/pause/seek, exposed as reactive streams with rxdart.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AudioHandler&lt;/strong&gt; — the background audio service that survives the app being backgrounded.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Background playback
&lt;/h2&gt;

&lt;p&gt;This is where most music apps fall apart. BeatNest combines &lt;strong&gt;just_audio&lt;/strong&gt; for the player with &lt;strong&gt;audio_service&lt;/strong&gt; for the OS-level media session. That gives you a notification with controls, lock-screen artwork, and playback that keeps going when the app is swiped away.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;dependencies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;just_audio&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;^0.10.5&lt;/span&gt;
  &lt;span class="na"&gt;audio_service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;^0.18.12&lt;/span&gt;
  &lt;span class="na"&gt;audio_session&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;^0.2.3&lt;/span&gt;
  &lt;span class="na"&gt;rxdart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;^0.28.0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Auth and cloud sync
&lt;/h2&gt;

&lt;p&gt;Users can continue as a guest or sign in with email or Google via &lt;strong&gt;Firebase Auth&lt;/strong&gt;. Signing in syncs their liked songs and playlists across devices through Cloud Firestore, so the library follows the user, not the phone.&lt;/p&gt;

&lt;h2&gt;
  
  
  Offline and resilience
&lt;/h2&gt;

&lt;p&gt;Downloads use &lt;strong&gt;dio&lt;/strong&gt; with a local SQLite index so songs are available without a connection, and &lt;strong&gt;connectivity_plus&lt;/strong&gt; gracefully degrades the UI when the network drops. Crashes and usage are tracked with Firebase Crashlytics and Analytics.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lessons learned
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Treat the audio session as the source of truth — the UI should reflect it, never drive it directly.&lt;/li&gt;
&lt;li&gt;Background execution rules differ a lot between Android and iOS; test on real devices early.&lt;/li&gt;
&lt;li&gt;A "Continue as guest" path removes friction and still lets you upsell sync later.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;BeatNest started as an experiment in "can Flutter really do a proper media app?" The answer turned out to be a confident yes.&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>dart</category>
      <category>mobile</category>
      <category>music</category>
    </item>
    <item>
      <title>Angular Beyond the Docs: What 4+ Years of Production Code Taught Me</title>
      <dc:creator>Sanket Jagtap</dc:creator>
      <pubDate>Wed, 17 Jun 2026 16:54:24 +0000</pubDate>
      <link>https://dev.to/sanketjagtap1/angular-beyond-the-docs-what-4-years-of-production-code-taught-me-96o</link>
      <guid>https://dev.to/sanketjagtap1/angular-beyond-the-docs-what-4-years-of-production-code-taught-me-96o</guid>
      <description>&lt;h1&gt;
  
  
  Angular Beyond the Docs: What 4+ Years of Production Code Taught Me
&lt;/h1&gt;

&lt;p&gt;Most Angular blogs explain what a feature does.&lt;/p&gt;

&lt;p&gt;Very few talk about &lt;strong&gt;when it hurts, when it helps, and when not to use it&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;After more than &lt;strong&gt;4 years of building Angular applications in production&lt;/strong&gt; , I’ve learned that the hardest problems were never about syntax or APIs — they were about &lt;strong&gt;decisions&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This post is for developers who already know Angular and want to &lt;strong&gt;think more clearly while building real systems&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Real Problem Was Never Angular — It Was Over-Abstraction
&lt;/h2&gt;

&lt;p&gt;Early in my career, I believed:&lt;/p&gt;

&lt;p&gt;More architecture means better code.&lt;/p&gt;

&lt;p&gt;So I built:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;1. Deep folder hierarchies&lt;/li&gt;
&lt;li&gt;2. Over-generic services&lt;/li&gt;
&lt;li&gt;“Shared” modules that depended on everything&lt;/li&gt;
&lt;li&gt;Reusable components that were rarely reused&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The result wasn’t scalability — it was:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Slower development&lt;/li&gt;
&lt;li&gt;Harder onboarding&lt;/li&gt;
&lt;li&gt;Fear of touching existing code&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Modern Angular didn’t just introduce new features — it &lt;strong&gt;removed the need for unnecessary structure&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lesson:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Simplicity scales better than cleverness.&lt;/p&gt;

&lt;h2&gt;
  
  
  Signals Didn’t Replace RxJS — They Replaced Misuse of RxJS
&lt;/h2&gt;

&lt;p&gt;Signals are often described as &lt;em&gt;“Angular without RxJS.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That’s not accurate.&lt;/p&gt;

&lt;p&gt;RxJS was never the real problem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Using RxJS for synchronous UI state was.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What went wrong in real projects:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Observables for button state&lt;/li&gt;
&lt;li&gt;Subscriptions inside components&lt;/li&gt;
&lt;li&gt;Boilerplate like &lt;code&gt;takeUntil(destroy$)&lt;/code&gt; everywhere&lt;/li&gt;
&lt;li&gt;UI bugs caused by async timing&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;What signals fixed:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;UI state became synchronous again&lt;/li&gt;
&lt;li&gt;No subscriptions&lt;/li&gt;
&lt;li&gt;No memory-leak anxiety&lt;/li&gt;
&lt;li&gt;Predictable rendering&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Lesson:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Signals didn’t replace RxJS — they rescued it from being overused.&lt;/p&gt;

&lt;p&gt;Today my rule is simple:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Signals → UI and local state&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;RxJS → async streams (HTTP, WebSockets)&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Change Detection Wasn’t Slow — Our Mental Model Was
&lt;/h2&gt;

&lt;p&gt;For years, Angular performance advice felt like magic spells:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use &lt;code&gt;OnPush&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Add &lt;code&gt;trackBy&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Avoid functions in templates&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We followed rules without understanding &lt;em&gt;why&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Signals changed this by making change detection &lt;strong&gt;explicit&lt;/strong&gt; :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Angular updates only what reads a signal&lt;/li&gt;
&lt;li&gt;Not the whole component tree&lt;/li&gt;
&lt;li&gt;Not “everything just in case”&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Lesson:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Performance improves when the framework matches how developers think.&lt;/p&gt;

&lt;h2&gt;
  
  
  Standalone Components Solved a Human Problem
&lt;/h2&gt;

&lt;p&gt;NgModules worked — but they created &lt;strong&gt;cognitive overhead&lt;/strong&gt; :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Where is this provided?&lt;/li&gt;
&lt;li&gt;Why is this imported here?&lt;/li&gt;
&lt;li&gt;Which module owns this component?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Standalone components didn’t just reduce code.&lt;/p&gt;

&lt;p&gt;They reduced &lt;strong&gt;questions&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Developers can now open a file and understand it without tracing imports across multiple modules.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lesson:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The best abstractions are the ones you don’t have to explain.&lt;/p&gt;

&lt;h2&gt;
  
  
  State Management Is a Cost — Not a Feature
&lt;/h2&gt;

&lt;p&gt;NgRx is powerful.&lt;/p&gt;

&lt;p&gt;It’s also expensive.&lt;/p&gt;

&lt;p&gt;In production, I’ve seen:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Simple apps buried under actions and reducers&lt;/li&gt;
&lt;li&gt;Teams afraid to touch state logic&lt;/li&gt;
&lt;li&gt;Bugs hidden behind boilerplate&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Signals enabled something important:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Local state that stays local.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;My approach today:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Start with signals&lt;/li&gt;
&lt;li&gt;Introduce heavier state management &lt;strong&gt;only when complexity demands it&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Lesson:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;State management should grow with the problem — not ahead of it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Biggest Angular Upgrade Is Restraint
&lt;/h2&gt;

&lt;p&gt;Modern Angular gives us:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Signals&lt;/li&gt;
&lt;li&gt;Standalone APIs&lt;/li&gt;
&lt;li&gt;Deferrable views&lt;/li&gt;
&lt;li&gt;Better performance tools&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;But the real upgrade isn’t knowing more APIs.&lt;/p&gt;

&lt;p&gt;It’s knowing &lt;strong&gt;when not to use them&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I now ask:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Does this abstraction reduce thinking?&lt;/li&gt;
&lt;li&gt;Will this still make sense in two years?&lt;/li&gt;
&lt;li&gt;Can someone else debug this easily?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Lesson:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Senior Angular development is about clarity, not cleverness.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Angular today is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Faster&lt;/li&gt;
&lt;li&gt;Simpler&lt;/li&gt;
&lt;li&gt;More predictable&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;But frameworks don’t make applications maintainable — &lt;strong&gt;decisions do&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The best code is the one that survives change — not the one that impresses today.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>angular</category>
      <category>frontendengineering</category>
      <category>webdev</category>
      <category>architecture</category>
    </item>
  </channel>
</rss>
