<?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: Naveensivam S</title>
    <description>The latest articles on DEV Community by Naveensivam S (@naveensivam_s_767bb5c8004).</description>
    <link>https://dev.to/naveensivam_s_767bb5c8004</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3825618%2F3015b39f-cbb0-4800-b217-9da86cd0fd9f.png</url>
      <title>DEV Community: Naveensivam S</title>
      <link>https://dev.to/naveensivam_s_767bb5c8004</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/naveensivam_s_767bb5c8004"/>
    <language>en</language>
    <item>
      <title>Just a pr orchestrator</title>
      <dc:creator>Naveensivam S</dc:creator>
      <pubDate>Tue, 02 Jun 2026 10:12:48 +0000</pubDate>
      <link>https://dev.to/naveensivam_s_767bb5c8004/-4g83</link>
      <guid>https://dev.to/naveensivam_s_767bb5c8004/-4g83</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/naveensivam_s_767bb5c8004/prflow-from-abandoned-scaffold-to-a-production-grade-pr-orchestration-engine-21nd" class="crayons-story__hidden-navigation-link"&gt;PRFlow: From Abandoned Scaffold to a Production-Grade PR Orchestration Engine&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
      &lt;a href="https://dev.to/naveensivam_s_767bb5c8004/prflow-from-abandoned-scaffold-to-a-production-grade-pr-orchestration-engine-21nd" class="crayons-article__context-note crayons-article__context-note__feed"&gt;&lt;p&gt;GitHub “Finish-Up-A-Thon” Challenge Submission&lt;/p&gt;

&lt;/a&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/naveensivam_s_767bb5c8004" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3825618%2F3015b39f-cbb0-4800-b217-9da86cd0fd9f.png" alt="naveensivam_s_767bb5c8004 profile" class="crayons-avatar__image" width="96" height="96"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/naveensivam_s_767bb5c8004" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Naveensivam S
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Naveensivam S
                
              
              &lt;div id="story-author-preview-content-3802107" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/naveensivam_s_767bb5c8004" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3825618%2F3015b39f-cbb0-4800-b217-9da86cd0fd9f.png" class="crayons-avatar__image" alt="" width="96" height="96"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Naveensivam S&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/naveensivam_s_767bb5c8004/prflow-from-abandoned-scaffold-to-a-production-grade-pr-orchestration-engine-21nd" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jun 2&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/naveensivam_s_767bb5c8004/prflow-from-abandoned-scaffold-to-a-production-grade-pr-orchestration-engine-21nd" id="article-link-3802107"&gt;
          PRFlow: From Abandoned Scaffold to a Production-Grade PR Orchestration Engine
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/devchallenge"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;devchallenge&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/githubchallenge"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;githubchallenge&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/development"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;development&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/githubcopilot"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;githubcopilot&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/naveensivam_s_767bb5c8004/prflow-from-abandoned-scaffold-to-a-production-grade-pr-orchestration-engine-21nd" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;1&lt;span class="hidden s:inline"&gt; reaction&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/naveensivam_s_767bb5c8004/prflow-from-abandoned-scaffold-to-a-production-grade-pr-orchestration-engine-21nd#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              &lt;span class="hidden s:inline"&gt;Add Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            8 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
    </item>
    <item>
      <title>PRFlow: From Abandoned Scaffold to a Production-Grade PR Orchestration Engine</title>
      <dc:creator>Naveensivam S</dc:creator>
      <pubDate>Tue, 02 Jun 2026 10:09:28 +0000</pubDate>
      <link>https://dev.to/naveensivam_s_767bb5c8004/prflow-from-abandoned-scaffold-to-a-production-grade-pr-orchestration-engine-21nd</link>
      <guid>https://dev.to/naveensivam_s_767bb5c8004/prflow-from-abandoned-scaffold-to-a-production-grade-pr-orchestration-engine-21nd</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/github-2026-05-21"&gt;GitHub Finish-Up-A-Thon Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;PRFlow&lt;/strong&gt; is an event-driven pull request orchestration and intelligence platform for engineering organizations.&lt;/p&gt;

&lt;p&gt;The core idea: GitHub is great at storing code and showing you diffs. But it has no intelligence about &lt;em&gt;who&lt;/em&gt; should review &lt;em&gt;what&lt;/em&gt;, &lt;em&gt;how overloaded&lt;/em&gt; a reviewer already is, or &lt;em&gt;what happens&lt;/em&gt; when a review goes stale for 3 days and blocks a release.&lt;/p&gt;

&lt;p&gt;PRFlow owns that layer entirely. It sits alongside GitHub as an active workflow orchestrator — modeling developer expertise using decay curves, deterministically routing reviewers based on real familiarity scores, balancing workloads, and enforcing SLA accountability with a self-healing escalation engine that auto-reassigns stalled PRs before a manager even notices.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tech stack:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Java 21 / Spring Boot 3.x — core orchestration monolith, 4 processing engines&lt;/li&gt;
&lt;li&gt;TypeScript / Bun / Express — high-throughput webhook ingress gateway&lt;/li&gt;
&lt;li&gt;PostgreSQL + Flyway — transactional schema with 9 tables&lt;/li&gt;
&lt;li&gt;Valkey (Redis-compatible) — caching layer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔗 &lt;strong&gt;Repo:&lt;/strong&gt; &lt;a href="https://github.com/Naveensivam03/PrFlow" rel="noopener noreferrer"&gt;github.com/Naveensivam03/PrFlow&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Parameter&lt;/th&gt;
&lt;th&gt;Specification&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;System Architecture&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Modular Monolith / Event-Driven&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Active&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Backend Core&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Java 21 / Spring Boot 3.x&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Build Passing&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Ingress Layer&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;TypeScript / Bun / Express&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Build Passing&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Database Persist&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;PostgreSQL / Flyway&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Migrated&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cache Layer&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Valkey (Redis Compatibility)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Active&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Test Coverage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;18 Tests Ingress-to-Escalation&lt;/td&gt;
&lt;td&gt;&lt;code&gt;100% Success&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;


  
  Your browser does not support the video tag.


&lt;p&gt;To reproduce the full smoke test locally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 1. Spin up dependencies&lt;/span&gt;
docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; prflow-db &lt;span class="nt"&gt;-p&lt;/span&gt; 5432:5432 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;POSTGRES_DB&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;prflow_db &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;POSTGRES_USER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;prflow_app &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;change_me_in_local_env &lt;span class="se"&gt;\&lt;/span&gt;
  postgres:16

docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; prflow-valkey &lt;span class="nt"&gt;-p&lt;/span&gt; 6379:6379 valkey/valkey:8.0

&lt;span class="c"&gt;# 2. Run backend (Flyway migrations run automatically)&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;backend/spring-api
mvn spring-boot:run &lt;span class="nt"&gt;-Dspring-boot&lt;/span&gt;.run.arguments&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"--spring.datasource.password=change_me_in_local_env"&lt;/span&gt;

&lt;span class="c"&gt;# 3. Run webhook ingress&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;integrations/github-webhook-service
bun &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; bun run dev

&lt;span class="c"&gt;# 4. Run tests&lt;/span&gt;
mvn &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;span class="c"&gt;# → 18 tests, 0 failures&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The Comeback Story
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Where the project was
&lt;/h3&gt;

&lt;p&gt;I started PRFlow during a tight sprint. The monorepo scaffold was there. The README had grand architecture diagrams. The database schema was designed. And then I stopped.&lt;/p&gt;

&lt;p&gt;What actually existed when I came back:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A folder structure and an ambitious README&lt;/li&gt;
&lt;li&gt;Database migrations written, but never proven against real engine output&lt;/li&gt;
&lt;li&gt;Expertise model documented in &lt;code&gt;/docs&lt;/code&gt; but not implemented in code&lt;/li&gt;
&lt;li&gt;Assignment Engine: pseudocode logic in a half-written service class&lt;/li&gt;
&lt;li&gt;Escalation Engine: &lt;strong&gt;entirely missing&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Zero tests&lt;/li&gt;
&lt;li&gt;No idempotency — concurrent webhook retries would have caused duplicate assignments&lt;/li&gt;
&lt;li&gt;Webhook ingress had no cryptographic signature verification&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It was a graveyard of good intentions. The architecture was sound. The execution had never happened.&lt;/p&gt;

&lt;h3&gt;
  
  
  What I finished during this challenge
&lt;/h3&gt;

&lt;p&gt;Here is the before/after breakdown across every major component:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Before&lt;/th&gt;
&lt;th&gt;After&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Complexity Engine&lt;/td&gt;
&lt;td&gt;Partially written, not integrated&lt;/td&gt;
&lt;td&gt;Fully implemented, wired to event pipeline&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Expertise Engine&lt;/td&gt;
&lt;td&gt;Design doc only&lt;/td&gt;
&lt;td&gt;Linear decay curves, touch + review scores, DB upserts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Assignment Engine&lt;/td&gt;
&lt;td&gt;Pseudocode&lt;/td&gt;
&lt;td&gt;Deterministic scoring, load balancing, 3-stage fallback&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Escalation Engine&lt;/td&gt;
&lt;td&gt;Did not exist&lt;/td&gt;
&lt;td&gt;Full 3-tier SLA scanner with hourly cron, auto-reassignment&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Idempotency&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Atomic conditional SQL gates, replay hash checks, audit log boundary&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tests&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;18 tests, 100% passing, full ingress-to-escalation coverage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Webhook Security&lt;/td&gt;
&lt;td&gt;Unverified&lt;/td&gt;
&lt;td&gt;HMAC-SHA256 cryptographic signature verification&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Engine Packaging&lt;/td&gt;
&lt;td&gt;Flat service classes&lt;/td&gt;
&lt;td&gt;Refactored into &lt;code&gt;service/event/dto/repository&lt;/code&gt; layers&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




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

&lt;h3&gt;
  
  
  Core Philosophy
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  ┌────────────────────────┐         ┌────────────────────────┐
  │   GitHub App Ingress   │         │    PRFlow Core Engine  │
  ├────────────────────────┤         ├────────────────────────┤
  │ - Git Repositories     │         │ - Workflow State       │
  │ - Source Code Storage  ├────────&amp;gt;│ - Expertise Graphs     │
  │ - PR Visual UI         │         │ - SLA Escalations      │
  │ - Review Sync Hook     │         │ - Deterministic Routing│
  └────────────────────────┘         └────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub is the &lt;strong&gt;system of record&lt;/strong&gt; for code. PRFlow is the &lt;strong&gt;system of record for workflow intelligence.&lt;/strong&gt; They never overlap.&lt;/p&gt;

&lt;h3&gt;
  
  
  System Architecture Overview
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh3561ge9s35pmhrpjk68.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh3561ge9s35pmhrpjk68.png" alt="PRFlow system architecture diagram showing GitHub App Ingress connected to the PRFlow Core Engine. GitHub manages repositories, source code storage, pull request UI, and review synchronization, while PRFlow handles workflow state, expertise graphs, SLA escalations, and deterministic reviewer routing." width="799" height="361"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Core Workflow Lifecycle
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdlv708i0bwemx3nrnpaf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdlv708i0bwemx3nrnpaf.png" alt="Image of the workflow lifecycle of the prflow" width="800" height="1807"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  End-to-End Sequence Flow
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbua8cwoe8qxhbncwd9pc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbua8cwoe8qxhbncwd9pc.png" alt="Image of the end to end sequence flow of prflow" width="800" height="568"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The 4 Engine Pipeline
&lt;/h2&gt;

&lt;p&gt;PRFlow segments all workflow logic into four deterministic, replay-safe engines wired together through an internal Spring event bus.&lt;/p&gt;

&lt;h3&gt;
  
  
  Engine 1 — Complexity Engine
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Responsibility:&lt;/strong&gt; Calculates structural risk and engineering scope for every ingested PR.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Inputs: changed file counts, additions, deletions, directory hierarchy depth&lt;/li&gt;
&lt;li&gt;Output: &lt;code&gt;PullRequest.complexity_score&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Role: Entry point of the pipeline. PRs with complexity &amp;gt; 7.0 are gated — only senior engineers are eligible as reviewers.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Engine 2 — Expertise Engine
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Responsibility:&lt;/strong&gt; Computes real-time, decayed familiarity scores per developer per file path.&lt;/p&gt;

&lt;p&gt;The expertise model uses a &lt;strong&gt;linear decay curve&lt;/strong&gt; — knowledge fades with time since a developer last touched or reviewed a file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Weight = 1.0   (touch &amp;lt; 30 days ago)     → fresh
       = 0.7   (30–90 days ago)          → fading
       = 0.4   (90–180 days ago)         → stale
       = 0.1   (&amp;gt; 180 days ago)          → nearly forgotten
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Review actions carry bonus weight — active intellectual contribution matters more than a passive file touch:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ReviewScore = (Participation × 1.0) + (Approval × 2.0)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Outputs: upserts to &lt;code&gt;developer_file_expertise&lt;/code&gt;, emits &lt;code&gt;ExpertiseCalculatedEvent&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Role: Accumulates organic organizational memory. No manual domain lists. Knowledge maps itself.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Engine 3 — Assignment Engine
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Responsibility:&lt;/strong&gt; Deterministically routes PRs to optimal reviewer combinations while balancing workload.&lt;/p&gt;

&lt;p&gt;The scoring formula penalizes reviewers who are already overloaded:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Score = ExpertiseScore / (1.0 + (ActiveReviewsCount × 2.0))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;ActiveReviewsCount&lt;/code&gt; only counts assignments with status &lt;code&gt;ASSIGNED&lt;/code&gt;, &lt;code&gt;REMINDER_SENT&lt;/code&gt;, or &lt;code&gt;STALE&lt;/code&gt; — open and stalled work counts against you.&lt;/p&gt;

&lt;p&gt;The engine then applies a 3-stage fallback if the target reviewer count can't be filled:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Femjp1kk8yjgkhjz4grru.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Femjp1kk8yjgkhjz4grru.png" alt="Assignment Engine fallback workflow showing three reviewer selection stages: expertise-based reviewer assignment, expanded candidate search when insufficient reviewers are available, and final fallback assignment using repository contributors to satisfy reviewer requirements." width="799" height="149"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Engine 4 — Escalation Engine
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Responsibility:&lt;/strong&gt; Monitors review response latency against SLA limits and triggers restorative workflows.&lt;/p&gt;

&lt;p&gt;An hourly scheduled scanner evaluates all open &lt;code&gt;reviewer_assignments&lt;/code&gt; against three progressive breach tiers:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5h0bqeomygmwwtoybt9o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5h0bqeomygmwwtoybt9o.png" alt="Escalation Engine SLA breach workflow showing three escalation levels: reminder notification for overdue reviews, stale review detection and escalation, and automatic reviewer reassignment when SLA thresholds are exceeded." width="749" height="981"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Transactional Idempotency
&lt;/h2&gt;

&lt;p&gt;This was one of the most important things I finished. Without it, any webhook retry would cause duplicate assignments and duplicate escalation emails.&lt;/p&gt;

&lt;p&gt;PRFlow applies three idempotency layers:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. State machine lockouts&lt;/strong&gt; — SLA transitions use atomic conditional SQL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;reviewer_assignments&lt;/span&gt;
&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;assignment_status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'REMINDER_SENT'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;reminder_sent_at&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;NOW&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="n"&gt;escalation_level&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;pull_request_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;developer_id&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;escalation_level&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;assignment_status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'ASSIGNED'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the scheduler fires twice concurrently, exactly one &lt;code&gt;UPDATE&lt;/code&gt; succeeds. The second hits the &lt;code&gt;AND escalation_level &amp;lt; 1&lt;/code&gt; gate and affects 0 rows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Review sync replay gating&lt;/strong&gt; — &lt;code&gt;ReviewSyncService&lt;/code&gt; checks state hashes before storing reviews. Identical state = ignored replay.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Audit log ingress boundary&lt;/strong&gt; — A dedicated &lt;code&gt;webhook_logs&lt;/code&gt; table records every inbound payload with its HMAC signature. Duplicates are caught at the door before entering the engine pipeline.&lt;/p&gt;




&lt;h2&gt;
  
  
  Database Schema
&lt;/h2&gt;

&lt;p&gt;The persistence model uses 9 tables in a PostgreSQL transactional schema, managed entirely via Flyway migrations.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;              ┌─────────────────┐
              │  organizations  │
              └────────┬────────┘
                       │ 1
                       │ *
              ┌────────┴────────┐
              │   developers    │
              └────────┬────────┘
                       │ 1
                       │ *
              ┌────────┴────────┐
              │   assignments   │
              └────────┬────────┘
                       │ *
                       │ 1
              ┌────────┴────────┐
              │  pull_requests  │
              └─────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Table&lt;/th&gt;
&lt;th&gt;Core Rationale&lt;/th&gt;
&lt;th&gt;Key Indexes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;organizations&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Defines org boundary matching a GitHub App installation scope&lt;/td&gt;
&lt;td&gt;&lt;code&gt;uq_organizations_name&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;developers&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Contributor registry — username, seniority, active review capacity, reliability&lt;/td&gt;
&lt;td&gt;&lt;code&gt;idx_developers_org_github&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;repositories&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Code repos mapped to org boundaries&lt;/td&gt;
&lt;td&gt;&lt;code&gt;idx_repos_org_github_repo&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pull_requests&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Persistent PR lifecycle metadata — title, author, complexity, status&lt;/td&gt;
&lt;td&gt;&lt;code&gt;idx_pr_repository_status&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pull_request_files&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Changed files and domain scopes per PR&lt;/td&gt;
&lt;td&gt;&lt;code&gt;idx_pr_files_pr_id&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;developer_file_expertise&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Organic knowledge base — touch and review scores per developer per file&lt;/td&gt;
&lt;td&gt;&lt;code&gt;uq_dev_repo_file_path&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;repository_developers&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Many-to-many linking active developers to repositories&lt;/td&gt;
&lt;td&gt;&lt;code&gt;uq_repository_developers&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;reviewer_assignments&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Workflow state machine — score, status, SLA level, timestamps&lt;/td&gt;
&lt;td&gt;&lt;code&gt;idx_reviewer_assignments_status&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pull_request_reviews&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Historic review memory synced from GitHub&lt;/td&gt;
&lt;td&gt;&lt;code&gt;uq_github_review_id&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Monorepo Structure
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.
├── backend/spring-api/          # Core Java 21 / Spring Boot Orchestration Monolith
│   ├── src/main/java/           # Engines, services, events, db gateways
│   └── src/main/resources/      # Flyway migrations and config
├── integrations/
│   └── github-webhook-service/  # TypeScript / Bun Webhook Ingestion Service
├── docs/
│   ├── engines/                 # Engine design guides
│   └── database/                # Schema design guides
├── infra/                       # Infrastructure configurations
└── README.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  My Experience with GitHub Copilot
&lt;/h2&gt;

&lt;p&gt;GitHub Copilot was genuinely the difference between this project staying abandoned and actually shipping.&lt;/p&gt;

&lt;p&gt;Here's exactly how it helped, with no fluff:&lt;/p&gt;

&lt;h3&gt;
  
  
  Engine package refactoring
&lt;/h3&gt;

&lt;p&gt;My engine classes had grown into a tangled mess — services calling each other directly, no clean event/dto/repository separation. I used Copilot to systematically refactor each engine into proper layered packages. It caught coupling violations I would have shipped as permanent tech debt and suggested the right abstraction boundaries for each layer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Idempotency SQL patterns
&lt;/h3&gt;

&lt;p&gt;Writing atomic conditional &lt;code&gt;UPDATE&lt;/code&gt; statements for SLA state machine transitions is subtle. You need to check both the current status AND the escalation level in the same &lt;code&gt;WHERE&lt;/code&gt; clause to prevent duplicate dispatches under concurrent execution. Copilot suggested the exact gating pattern on the first attempt. Without it, I would have spent hours debugging phantom duplicate escalation emails in testing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Test scaffolding
&lt;/h3&gt;

&lt;p&gt;I described the coverage requirements — full ingress-to-escalation, including edge cases for replay-safe review sync — and Copilot generated the 18-test suite structure. It included edge cases I hadn't thought about: what happens when a review sync arrives with an identical state hash, what happens when the escalation scanner fires on an assignment that was just reassigned by a concurrent webhook.&lt;/p&gt;

&lt;h3&gt;
  
  
  Decay curve implementation
&lt;/h3&gt;

&lt;p&gt;Translating the 4-tier linear recency weight formula into correct JPA query logic (with proper &lt;code&gt;TIMESTAMPDIFF&lt;/code&gt; comparisons relative to &lt;code&gt;opened_at&lt;/code&gt;) was something Copilot nailed cleanly. This kind of time-arithmetic SQL is easy to get subtly wrong.&lt;/p&gt;

&lt;h3&gt;
  
  
  Logging hygiene refactor
&lt;/h3&gt;

&lt;p&gt;The most recent commit in the repo was a Copilot-assisted refactor. It helped strip verbose debug logging across all four engines while identifying which audit-critical log lines must be preserved. This is surprisingly judgment-heavy — you don't want to remove the log line that traces a missed escalation — and Copilot handled it well by reasoning about which paths were observability-critical.&lt;/p&gt;

&lt;h3&gt;
  
  
  The bigger shift
&lt;/h3&gt;

&lt;p&gt;The most valuable thing Copilot did wasn't any single code block. It kept me in &lt;strong&gt;architecture mode&lt;/strong&gt; instead of constantly context-switching into syntax lookup. I could describe what I wanted at the system level and get working, idiomatic Java back fast enough that I never lost the thread of what I was building. That's what got a dormant project across the finish line.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;The core platform is production-complete. The roadmap has three realistic extensions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Review Latency Insights&lt;/strong&gt; — historic trend dashboards tracking avg cycle time per reviewer, per complexity tier, per repository&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ownership Heatmaps&lt;/strong&gt; — map file directories to knowledge concentration indexes, expose bottlenecks and single-points-of-failure&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Workload Forecasting&lt;/strong&gt; — predictive charts estimating future reviewer capacity limits from current branch activity&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Running It Yourself
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;JDK 21&lt;/li&gt;
&lt;li&gt;Bun&lt;/li&gt;
&lt;li&gt;Docker
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Bootstrap PostgreSQL and Valkey&lt;/span&gt;
docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; prflow-db &lt;span class="nt"&gt;-p&lt;/span&gt; 5432:5432 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;POSTGRES_DB&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;prflow_db &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;POSTGRES_USER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;prflow_app &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;change_me_in_local_env &lt;span class="se"&gt;\&lt;/span&gt;
  postgres:16

docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; prflow-valkey &lt;span class="nt"&gt;-p&lt;/span&gt; 6379:6379 valkey/valkey:8.0

&lt;span class="c"&gt;# Start the backend (migrations run automatically via Flyway)&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;backend/spring-api
mvn spring-boot:run &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-Dspring-boot&lt;/span&gt;.run.arguments&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"--spring.datasource.password=change_me_in_local_env"&lt;/span&gt;

&lt;span class="c"&gt;# Start the webhook ingress gateway&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;integrations/github-webhook-service
bun &lt;span class="nb"&gt;install
&lt;/span&gt;bun run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To wire up a real GitHub App, expose port &lt;code&gt;3001&lt;/code&gt; via &lt;code&gt;ngrok http 3001&lt;/code&gt;, point your GitHub App webhook URL there, set &lt;code&gt;Pull Requests: Read &amp;amp; Write&lt;/code&gt; and &lt;code&gt;Metadata: Read-Only&lt;/code&gt; permissions, and drop your generated private key into the config folder.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built with Java 21 · Spring Boot 3.x · TypeScript · Bun · PostgreSQL · Valkey · GitHub Copilot&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>githubchallenge</category>
      <category>development</category>
      <category>githubcopilot</category>
    </item>
    <item>
      <title>trapping rainwater</title>
      <dc:creator>Naveensivam S</dc:creator>
      <pubDate>Sat, 30 May 2026 06:24:10 +0000</pubDate>
      <link>https://dev.to/naveensivam_s_767bb5c8004/trapping-rainwater-459j</link>
      <guid>https://dev.to/naveensivam_s_767bb5c8004/trapping-rainwater-459j</guid>
      <description>&lt;h2&gt;
  
  
  Problem: Trapping rain water.
&lt;/h2&gt;

&lt;h2&gt;
  
  
  code:
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Solution&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;trap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="n"&gt;maxl&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;maxr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="n"&gt;water&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="n"&gt;maxwater&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; 
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;maxl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;maxl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;water&lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="n"&gt;maxl&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
            &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt;&lt;span class="n"&gt;maxr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;maxr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;water&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="n"&gt;maxr&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;-=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;water&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  time complexity: O(n)
&lt;/h2&gt;

&lt;h2&gt;
  
  
  space complexity: O(1)
&lt;/h2&gt;

</description>
      <category>leetcode</category>
      <category>interview</category>
      <category>career</category>
    </item>
    <item>
      <title>Linkedlist leetcode</title>
      <dc:creator>Naveensivam S</dc:creator>
      <pubDate>Sat, 30 May 2026 06:00:31 +0000</pubDate>
      <link>https://dev.to/naveensivam_s_767bb5c8004/linkedlist-leetcode-fc3</link>
      <guid>https://dev.to/naveensivam_s_767bb5c8004/linkedlist-leetcode-fc3</guid>
      <description>&lt;h2&gt;
  
  
  cloning the ll into another using deep copy
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;initially we use hashmap to implement it .
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
# Definition for a Node.
class Node:
    def __init__(self, x: int, next: &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Node&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; = None, random: &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Node&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; = None):
        self.val = int(x)
        self.next = next
        self.random = random
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Solution&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;copyRandomList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Optional[Node]&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Optional[Node]&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
        &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; 
        &lt;span class="n"&gt;curr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;head&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;curr&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;curr&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;curr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
            &lt;span class="n"&gt;curr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;curr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt;
        &lt;span class="n"&gt;curr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;head&lt;/span&gt;

        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;curr&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;copy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;curr&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;# this is where we are copying inside the dictionary itself.
&lt;/span&gt;            &lt;span class="n"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;curr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;curr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;curr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;curr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt;
        &lt;span class="n"&gt;curr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;head&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;curr&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Time complexity :
&lt;/h3&gt;

&lt;p&gt;O(n)&lt;/p&gt;

&lt;h3&gt;
  
  
  space complexity
&lt;/h3&gt;

&lt;p&gt;O(n)   # which is bad &lt;/p&gt;

&lt;h1&gt;
  
  
  optimization
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;we need to reduce space complexity alone.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
# Definition for a Node.
class Node:
    def __init__(self, x: int, next: &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Node&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; = None, random: &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Node&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; = None):
        self.val = int(x)
        self.next = next
        self.random = random
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Solution&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;copyRandomList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Optional[Node]&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Optional[Node]&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# if not head:
&lt;/span&gt;        &lt;span class="c1"&gt;#     return None
&lt;/span&gt;        &lt;span class="c1"&gt;# h = {} 
&lt;/span&gt;        &lt;span class="c1"&gt;# curr = head
&lt;/span&gt;        &lt;span class="c1"&gt;# while curr != None:
&lt;/span&gt;        &lt;span class="c1"&gt;#     h[curr] = Node(curr.val) 
&lt;/span&gt;        &lt;span class="c1"&gt;#     curr = curr.next
&lt;/span&gt;        &lt;span class="c1"&gt;# curr = head
&lt;/span&gt;
        &lt;span class="c1"&gt;# while curr != None:
&lt;/span&gt;        &lt;span class="c1"&gt;#     copy = h[curr]
&lt;/span&gt;        &lt;span class="c1"&gt;#     copy.next = h.get(curr.next)
&lt;/span&gt;        &lt;span class="c1"&gt;#     copy.random = h.get(curr.random)
&lt;/span&gt;        &lt;span class="c1"&gt;#     curr = curr.next
&lt;/span&gt;        &lt;span class="c1"&gt;# curr = head
&lt;/span&gt;        &lt;span class="c1"&gt;# return h[curr]
&lt;/span&gt;
        &lt;span class="c1"&gt;# optimal solutions 
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

        &lt;span class="n"&gt;curr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;head&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;curr&lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;copy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;curr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;curr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt;
            &lt;span class="n"&gt;curr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;copy&lt;/span&gt; 
            &lt;span class="n"&gt;curr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;curr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt;
        &lt;span class="c1"&gt;# now the array will look like this " a-a'-b-b'-c-c'"
&lt;/span&gt;
        &lt;span class="n"&gt;curr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;head&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;curr&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;curr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;curr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;curr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt;
            &lt;span class="n"&gt;curr&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;curr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt;
        &lt;span class="c1"&gt;# now it will point the random too since curr.next.random is for copied part and curr.random.next is for copied partof random.
&lt;/span&gt;
        &lt;span class="c1"&gt;# now we need to separate 
&lt;/span&gt;        &lt;span class="n"&gt;curr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;head&lt;/span&gt;
        &lt;span class="n"&gt;curr_head&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;curr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;curr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;copy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;curr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt;
            &lt;span class="n"&gt;curr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt;
            &lt;span class="n"&gt;curr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;curr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;curr_head&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;now it has O(1) space complexity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;Interview Explanation:&lt;br&gt;
    Initially we plan using hashmap which will use lookup of O(1) but we need space complexity of O(1) , to overcome it , we are use the same array , by inserting the copied inside the real linked list. and at last splitting that into two linkedlist.&lt;/code&gt;&lt;/p&gt;

</description>
      <category>leetcode</category>
      <category>interview</category>
      <category>techtalks</category>
    </item>
    <item>
      <title>I wasted the first hour of every new project doing the same thing — so I built a fix</title>
      <dc:creator>Naveensivam S</dc:creator>
      <pubDate>Sun, 15 Mar 2026 16:50:47 +0000</pubDate>
      <link>https://dev.to/naveensivam_s_767bb5c8004/i-wasted-the-first-hour-of-every-new-project-doing-the-same-thing-so-i-built-a-fix-mkm</link>
      <guid>https://dev.to/naveensivam_s_767bb5c8004/i-wasted-the-first-hour-of-every-new-project-doing-the-same-thing-so-i-built-a-fix-mkm</guid>
      <description>&lt;p&gt;Let me describe your last few new projects.&lt;/p&gt;

&lt;p&gt;You open your IDE. You create a Spring Boot project. &lt;br&gt;
You create a Next.js project. You start wiring them together.&lt;/p&gt;

&lt;p&gt;Then it begins.&lt;/p&gt;

&lt;p&gt;CORS error. Google it. Fix it. Wrong fix. Fix it again.&lt;br&gt;
Docker Compose. Which image? Which port? Healthcheck syntax?&lt;br&gt;
JPA config. Which dialect? Which DDL mode?&lt;br&gt;
AI tool opens. "Hey Claude, here is my project structure..." &lt;br&gt;
Re-explain everything from scratch. Again.&lt;/p&gt;

&lt;p&gt;One hour gone. You have not written a single line of &lt;br&gt;
business logic yet.&lt;/p&gt;

&lt;p&gt;I did this on five consecutive projects before I got &lt;br&gt;
frustrated enough to do something about it.&lt;/p&gt;


&lt;h2&gt;
  
  
  What I built
&lt;/h2&gt;

&lt;p&gt;Zovlyn is a project generator for Next.js + Spring Boot &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PostgreSQL.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You pick your options. You click Generate. You download &lt;br&gt;
a ZIP. You unzip it and run it.&lt;/p&gt;

&lt;p&gt;That is the entire experience.&lt;/p&gt;

&lt;p&gt;No account. No login. No credit card.&lt;/p&gt;

&lt;p&gt;👉  &lt;a href="https://zvolyn.vercel.app/" rel="noopener noreferrer"&gt;https://zvolyn.vercel.app/&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  What is actually inside the ZIP
&lt;/h2&gt;

&lt;p&gt;This is not just a GitHub template you clone and hope works.&lt;br&gt;
Every generated project includes:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CORS pre-wired using the proxy pattern&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Next.js frontend proxies all /api/* requests to Spring &lt;br&gt;
Boot server-side. The browser never touches port 8080 &lt;br&gt;
directly. Zero CORS errors in development. Zero config &lt;br&gt;
for production. This one decision alone saves most &lt;br&gt;
developers 30-60 minutes on every new project.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PostgreSQL connected with Spring profiles&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Three profiles are ready out of the box:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;local: connects to your machine on localhost:5432&lt;/li&gt;
&lt;li&gt;docker: connects to the postgres container by service name&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Switch environments by changing one line in application.yml.&lt;br&gt;
No Java code changes. No property hunting.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Docker Compose that actually works&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;PostgreSQL container with a healthcheck. Spring Boot &lt;br&gt;
waits for the database to be healthy before starting.&lt;br&gt;
Named volumes. Isolated network. One command:&lt;/p&gt;

&lt;p&gt;docker compose up --build&lt;/p&gt;

&lt;p&gt;Everything starts in the right order. The database &lt;br&gt;
is created automatically. No manual psql commands needed &lt;br&gt;
for Docker mode.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Three AGENTS.md files&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is the part I am most proud of.&lt;/p&gt;

&lt;p&gt;Every generated project includes an AGENTS.md file at &lt;br&gt;
the root, inside backend/, and inside frontend/.&lt;/p&gt;

&lt;p&gt;Each one explains the architecture, the conventions, &lt;br&gt;
the profile system, how to add a feature, and what &lt;br&gt;
each folder is for — written specifically for AI &lt;br&gt;
coding agents.&lt;/p&gt;

&lt;p&gt;When you open the project with Claude Code or Cursor, &lt;br&gt;
the AI reads these files first. It immediately understands:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;how the two services connect&lt;/li&gt;
&lt;li&gt;why the proxy pattern is used&lt;/li&gt;
&lt;li&gt;how to add a new endpoint correctly&lt;/li&gt;
&lt;li&gt;what profile to use for what environment&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You never re-explain your architecture to an AI tool again.&lt;br&gt;
Ever.&lt;/p&gt;


&lt;h2&gt;
  
  
  How it compares to existing starters
&lt;/h2&gt;

&lt;p&gt;There is a great Spring Boot + Next.js starter kit by &lt;br&gt;
Nermin Karapandzic on dev.to that includes authentication, &lt;br&gt;
OAuth2, RBAC, email sending, and S3 integration.&lt;/p&gt;

&lt;p&gt;That project is excellent if you need all of that.&lt;/p&gt;

&lt;p&gt;Zovlyn is the opposite. No auth. No opinions on your &lt;br&gt;
feature set. No complexity you have to untangle before &lt;br&gt;
you can start.&lt;/p&gt;

&lt;p&gt;Just the plumbing. Wired correctly. Ready to build on.&lt;/p&gt;

&lt;p&gt;If you know what you are building and you just want &lt;br&gt;
the foundation to work — Zovlyn is for you.&lt;/p&gt;


&lt;h2&gt;
  
  
  The technical decisions worth knowing
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Why the proxy pattern instead of CORS headers?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Because CORS header configuration is environment-specific, &lt;br&gt;
easy to get wrong, and exposes your backend URL in the &lt;br&gt;
browser. The proxy pattern solves all three problems at &lt;br&gt;
once. The backend URL never reaches the client. There &lt;br&gt;
are no environment-specific CORS rules to maintain. &lt;br&gt;
It just works.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Spring profiles instead of environment variables?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Because profiles let you switch the entire database &lt;br&gt;
configuration with one value. SPRING_PROFILES_ACTIVE=docker &lt;br&gt;
and your app connects to the container. Change it to local &lt;br&gt;
and it connects to your machine. No URL construction. &lt;br&gt;
No variable juggling.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why AGENTS.md instead of just a README?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A README is written for humans reading linearly. &lt;br&gt;
AGENTS.md files are structured for AI tools scanning &lt;br&gt;
for context. They answer the questions AI tools ask &lt;br&gt;
most often: what is this project, what are the &lt;br&gt;
conventions, how do I add a feature, what should I &lt;br&gt;
never do here. The structure matters as much as the &lt;br&gt;
content.&lt;/p&gt;


&lt;h2&gt;
  
  
  What is coming in v2
&lt;/h2&gt;

&lt;p&gt;Based on what developers have been asking for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;postgres as a first-class database option&lt;/li&gt;
&lt;li&gt;Spring Security scaffold with JWT&lt;/li&gt;
&lt;li&gt;More frontend options&lt;/li&gt;
&lt;li&gt;CLI tool so you never need the website&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://zvolyn.vercel.app/" rel="noopener noreferrer" class="c-link"&gt;
            Zovlyn — Full-Stack Project Generator
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Generate a pre-wired Next.js + Spring Boot + PostgreSQL project in seconds. CORS handled. Docker ready. AGENTS.md included for AI coding tools.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fzvolyn.vercel.app%2Ffavicon.ico%3Ffavicon.0b3bf435.ico"&gt;
          zvolyn.vercel.app
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;




&lt;p&gt;Generate a project right now. It takes 30 seconds.&lt;br&gt;
Unzip it. Run it. Tell me what breaks.&lt;/p&gt;

&lt;p&gt;I am genuinely looking for feedback from developers &lt;br&gt;
who build with Spring Boot and Next.js. What is missing? &lt;br&gt;
What is wrong? What would make this the tool you &lt;br&gt;
reach for on every new project?&lt;/p&gt;

&lt;p&gt;Drop a comment below !&lt;/p&gt;

&lt;p&gt;If you have been building Spring Boot + Next.js projects &lt;br&gt;
and have opinions on what a clean starter should include &lt;br&gt;
— I want to hear them.&lt;/p&gt;

</description>
      <category>springboot</category>
      <category>java</category>
      <category>freelance</category>
      <category>nextjs</category>
    </item>
  </channel>
</rss>
