<?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: Jufianto Henri</title>
    <description>The latest articles on DEV Community by Jufianto Henri (@jufianto).</description>
    <link>https://dev.to/jufianto</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%2F710116%2F23324c26-72a8-4fbf-8945-a37ac422ed34.jpeg</url>
      <title>DEV Community: Jufianto Henri</title>
      <link>https://dev.to/jufianto</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jufianto"/>
    <language>en</language>
    <item>
      <title>Queue vs Direct Insert: What Happens When 10,000 Users Hit Your Database at Once</title>
      <dc:creator>Jufianto Henri</dc:creator>
      <pubDate>Wed, 25 Feb 2026 14:00:16 +0000</pubDate>
      <link>https://dev.to/jufianto/queue-vs-direct-insert-what-happens-when-10000-users-hit-your-database-at-once-4b6</link>
      <guid>https://dev.to/jufianto/queue-vs-direct-insert-what-happens-when-10000-users-hit-your-database-at-once-4b6</guid>
      <description>&lt;p&gt;I've run online exam systems before.&lt;/p&gt;

&lt;p&gt;For a middle school with around 1,000 students, I needed a database server with 4 CPUs and 8GB RAM, plus an app server with 2 CPUs and 8GB RAM. That's a lot of hardware just for 1,000 users.&lt;/p&gt;

&lt;p&gt;The system worked, but I kept wondering — what if I had 10,000 students? Would I need 10x the resources?&lt;/p&gt;

&lt;p&gt;So I built two versions of an exam submission system and threw 10,000 concurrent users at them. One used direct database inserts. One used a message queue.&lt;/p&gt;

&lt;p&gt;Direct insert failed 28% of requests. Queue-based succeeded 99.7% of the time — using way less hardware.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;If you've run an online exam system, you know how this goes. Testing with 10 users works perfectly. QA with 50 concurrent users is fine. Then exam day hits with 1,000+ students and you're just hoping the server survives.&lt;/p&gt;

&lt;p&gt;Running exams for around 1,000 middle school students taught me that you need serious hardware just to handle everyone hitting the system at the same time. They all log in together. They all submit together. And when it lags, they all refresh together.&lt;/p&gt;

&lt;p&gt;Here's what actually happened during one of our exams:&lt;/p&gt;

&lt;p&gt;The moment the exam started, all 1,000 students tried to log in simultaneously. But it wasn't just them — we had no idea who else was hitting the system. Curious parents checking if the portal was up? Random people who found the URL? Someone trying to probe for vulnerabilities? All of it piled on top of our legitimate traffic.&lt;/p&gt;

&lt;p&gt;The result? &lt;strong&gt;CPU spiked to 80%. RAM hit 80%.&lt;/strong&gt; The login requests were stacking up faster than the server could process them.&lt;/p&gt;

&lt;p&gt;I had to make an embarrassing call: ask teachers to &lt;strong&gt;stagger logins by class&lt;/strong&gt;, waiting 10-15 minutes between groups. Imagine telling anxious students "please wait, the system can't handle everyone at once." Not a great look.&lt;/p&gt;

&lt;p&gt;And that was with "only" 1,000 users on a 4 CPU / 8GB database server.&lt;/p&gt;

&lt;p&gt;But here's what kept me up at night: &lt;strong&gt;What happens at 10,000 users?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;At that scale, your API receives &lt;strong&gt;3,000 requests per second&lt;/strong&gt;. A typical PostgreSQL connection pool maxes out at 100 connections.&lt;/p&gt;

&lt;p&gt;Do the math: &lt;strong&gt;3,000 requests competing for 100 database connections.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I had to see this for myself.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Test Setup
&lt;/h2&gt;

&lt;p&gt;I built two identical exam submission APIs in Go:&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;Direct Insert (Port 8080)&lt;/th&gt;
&lt;th&gt;Queue-Based (Port 8081)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;API Server&lt;/td&gt;
&lt;td&gt;Go + Fiber&lt;/td&gt;
&lt;td&gt;Go + Fiber&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Database&lt;/td&gt;
&lt;td&gt;PostgreSQL (1 CPU, 512MB)&lt;/td&gt;
&lt;td&gt;PostgreSQL (1 CPU, 512MB)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Message Queue&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;NATS JetStream&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Workers&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;10 concurrent workers&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Notice the database specs: 1 CPU, 512MB RAM. My real exam system needed 4 CPUs and 8GB RAM for just 1,000 students. I wanted to see if architecture choices could make up for limited hardware.&lt;/p&gt;

&lt;h3&gt;
  
  
  Load Test Configuration
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Concurrent Users&lt;/strong&gt;: 10,000 students&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Peak Load&lt;/strong&gt;: 3,000 requests/second&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Duration&lt;/strong&gt;: 5 minutes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tool&lt;/strong&gt;: k6 load testing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Same traffic. Same database. Two different architectures.&lt;/p&gt;




&lt;h2&gt;
  
  
  Approach 1: Direct Database Insert
&lt;/h2&gt;

&lt;p&gt;The straightforward approach. User submits → API writes to database → Return response.&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%2Fhak9qhnjyupz4qu0a6a7.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%2Fhak9qhnjyupz4qu0a6a7.png" alt="Direct Database Insert" width="800" height="2041"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;3,000 requests fighting for 100 database connections. The other 2,900? They wait. And wait. And eventually... timeout.&lt;/p&gt;




&lt;h2&gt;
  
  
  Approach 2: Queue-Based Architecture
&lt;/h2&gt;

&lt;p&gt;The API doesn't talk to the database at all. It just publishes a message to a queue and responds immediately. Workers consume messages in the background at whatever pace the database can handle.&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%2Fznr77u9azn9esjhap0ov.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%2Fznr77u9azn9esjhap0ov.png" alt="Queue Based Architechture" width="800" height="2799"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The queue acts as a shock absorber. Traffic spikes hit the queue, not your database.&lt;/p&gt;




&lt;h2&gt;
  
  
  Results
&lt;/h2&gt;

&lt;p&gt;I expected the queue to win. I didn't expect it to be a blowout.&lt;/p&gt;

&lt;h3&gt;
  
  
  Response Time Comparison
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Direct Insert&lt;/th&gt;
&lt;th&gt;Queue-Based&lt;/th&gt;
&lt;th&gt;Improvement&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Average&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;487ms&lt;/td&gt;
&lt;td&gt;8ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;60x faster&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;P50 (median)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;392ms&lt;/td&gt;
&lt;td&gt;6ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;65x faster&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;P95&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1,245ms&lt;/td&gt;
&lt;td&gt;18ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;69x faster&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;P99&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;2,891ms&lt;/td&gt;
&lt;td&gt;34ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;85x faster&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Maximum&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;8,432ms&lt;/td&gt;
&lt;td&gt;127ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;66x faster&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Success Rate Comparison
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Approach&lt;/th&gt;
&lt;th&gt;Successful&lt;/th&gt;
&lt;th&gt;Failed&lt;/th&gt;
&lt;th&gt;Success Rate&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Direct Insert&lt;/td&gt;
&lt;td&gt;12,459&lt;/td&gt;
&lt;td&gt;4,831&lt;/td&gt;
&lt;td&gt;72.1%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Queue-Based&lt;/td&gt;
&lt;td&gt;17,234&lt;/td&gt;
&lt;td&gt;56&lt;/td&gt;
&lt;td&gt;99.7%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;With direct insert, &lt;strong&gt;28% of exam submissions failed&lt;/strong&gt;. In a real exam scenario, that's potentially thousands of students who need to resubmit, file complaints, or worse — lose their work entirely.&lt;/p&gt;

&lt;h3&gt;
  
  
  Database Resource Usage
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Direct Insert&lt;/th&gt;
&lt;th&gt;Queue-Based&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;DB Connections&lt;/td&gt;
&lt;td&gt;98-100 (maxed out)&lt;/td&gt;
&lt;td&gt;12-18&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CPU Usage&lt;/td&gt;
&lt;td&gt;95-100%&lt;/td&gt;
&lt;td&gt;35-60%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Query Queue&lt;/td&gt;
&lt;td&gt;Backed up&lt;/td&gt;
&lt;td&gt;Smooth&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The direct approach pushed the database to its absolute limit. The queue approach? The database barely noticed.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Did Direct Insert Fail?
&lt;/h2&gt;

&lt;p&gt;Analyzing the 28% failure rate, here's the breakdown:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Error Type&lt;/th&gt;
&lt;th&gt;Percentage&lt;/th&gt;
&lt;th&gt;What Happened&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Connection Timeout&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;52%&lt;/td&gt;
&lt;td&gt;Connection pool exhausted, requests waited &amp;gt; 10s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Database Deadlock&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;23%&lt;/td&gt;
&lt;td&gt;Too many concurrent writes, lock contention&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Connection Refused&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;18%&lt;/td&gt;
&lt;td&gt;Max connections reached, new ones rejected&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Context Canceled&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;7%&lt;/td&gt;
&lt;td&gt;Users gave up waiting&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The connection pool was the bottleneck. No matter how fast your database is, it can only handle so many concurrent connections.&lt;/p&gt;




&lt;h2&gt;
  
  
  The User Experience Difference
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Direct Insert: The Frustrating Experience
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User clicks "Submit" 
    → Spinner...
    → Still waiting...
    → 3 seconds pass...
    → "Connection timeout" error

(28% of the time)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Average wait: &lt;strong&gt;487ms&lt;/strong&gt; (but often 1-3 seconds, sometimes 8+ seconds)&lt;/p&gt;

&lt;h3&gt;
  
  
  Queue-Based: The Smooth Experience
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User clicks "Submit"
    → "Submission received!"

(Processing happens in background)
(User continues immediately)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Average wait: &lt;strong&gt;8ms&lt;/strong&gt; (consistently fast)&lt;/p&gt;




&lt;h2&gt;
  
  
  What This Costs in Practice
&lt;/h2&gt;

&lt;p&gt;My original setup for ~1,000 users:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Database: 4 CPU, 8GB RAM&lt;/li&gt;
&lt;li&gt;App Server: 2 CPU, 8GB RAM
&lt;/li&gt;
&lt;li&gt;Monthly cost: around $200-300&lt;/li&gt;
&lt;li&gt;Stress level during exams: high&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The queue-based test with 10,000 users:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Database: 1 CPU, 512MB RAM&lt;/li&gt;
&lt;li&gt;Everything else: minimal&lt;/li&gt;
&lt;li&gt;Success rate: 99.7%&lt;/li&gt;
&lt;li&gt;The database didn't even notice the load&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's 10x the users with way less hardware.&lt;/p&gt;

&lt;h3&gt;
  
  
  Business Impact Comparison
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;Direct Insert&lt;/th&gt;
&lt;th&gt;Queue-Based&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;User Errors&lt;/td&gt;
&lt;td&gt;28% see failures&lt;/td&gt;
&lt;td&gt;0.3% see failures&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Infrastructure&lt;/td&gt;
&lt;td&gt;Need bigger DB for spikes&lt;/td&gt;
&lt;td&gt;Smaller DB handles more&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Exam Day Stress&lt;/td&gt;
&lt;td&gt;Engineers on-call&lt;/td&gt;
&lt;td&gt;System stays calm&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scalability&lt;/td&gt;
&lt;td&gt;Linear cost increase&lt;/td&gt;
&lt;td&gt;Efficient scaling&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  When to Use What
&lt;/h2&gt;

&lt;p&gt;Queues aren't always the answer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Direct insert works fine when&lt;/strong&gt; traffic is low and predictable, you need data in the database immediately (like real-time dashboards), or you're doing mostly reads with occasional writes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Queues make sense when&lt;/strong&gt; you have traffic spikes, lots of concurrent writes, users who care about response time, or you can't afford to lose data. The queue gives you a buffer — it absorbs the spike and lets workers process at whatever pace the database can handle.&lt;/p&gt;

&lt;p&gt;Think exam submissions, checkout during sales, ticket purchases, push notifications — anything where everyone hits the system at once.&lt;/p&gt;




&lt;h2&gt;
  
  
  How the Queue Architecture Works
&lt;/h2&gt;

&lt;p&gt;Here's how it works under the hood:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. API Layer (Fast Response)
&lt;/h3&gt;

&lt;p&gt;The API receives the exam submission and publishes it to NATS JetStream. No database call here — just a message publish (~2ms).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Pseudocode&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;submitExam&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;fiber&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;submission&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;parseRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Publish to queue (non-blocking, ~2ms)&lt;/span&gt;
    &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;nats&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Publish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"exam.submissions"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;submission&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;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Immediately respond to user&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Status&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"accepted"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;submission&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&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;h3&gt;
  
  
  2. Message Queue (Shock Absorber)
&lt;/h3&gt;

&lt;p&gt;NATS JetStream stores messages durably. Even if workers are slow, messages aren't lost. The queue absorbs traffic spikes and releases them at a steady pace.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Workers (Controlled Processing)
&lt;/h3&gt;

&lt;p&gt;10 concurrent workers pull messages from the queue. Each worker processes in batches of 100 records — reducing database round trips.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Pseudocode&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FetchBatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c"&gt;// Get 100 messages&lt;/span&gt;
        &lt;span class="n"&gt;submissions&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;parseAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BatchInsert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;submissions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c"&gt;// Single DB call for 100 records&lt;/span&gt;

        &lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AckAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;messages&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;h3&gt;
  
  
  4. Database (Happy and Healthy)
&lt;/h3&gt;

&lt;p&gt;Instead of 3,000 concurrent connections, the database sees a steady stream from 10 workers. CPU stays at 35-60%. No deadlocks. No timeouts.&lt;/p&gt;




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

&lt;p&gt;&lt;strong&gt;Connection pools have hard limits.&lt;/strong&gt; Doesn't matter how fast your database is — 3,000 requests can't share 100 connections without waiting. I learned this the hard way.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Queues trade immediate consistency for reliability.&lt;/strong&gt; The user gets a fast "accepted" response, but the data isn't in the database yet. For most write-heavy workloads, that tradeoff is worth it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The performance difference is huge.&lt;/strong&gt; Not 2x or 3x — we're talking 60-85x faster response times.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Queues handle spikes gracefully.&lt;/strong&gt; During a traffic spike, the queue just grows. Nothing crashes. When traffic drops, workers catch up. No 2 AM pages.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Architecture matters more than hardware.&lt;/strong&gt; My 1,000-user system needed 4 CPU and 8GB RAM. This queue-based test handled 10,000 users on 1 CPU and 512MB.&lt;/p&gt;

&lt;p&gt;Wish I'd known this earlier. Could've saved money and stress.&lt;/p&gt;




&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Queues aren't always the answer. But for traffic spikes and heavy writes? Worth considering.&lt;/p&gt;

&lt;p&gt;Looking back at my exam systems with their beefy servers, I wish I'd tried this sooner. Usually you trade performance for cost — this gave me both.&lt;/p&gt;

&lt;p&gt;Next time you're building something write-heavy, ask yourself: what happens when everyone hits it at once?&lt;/p&gt;




&lt;p&gt;Code is on GitHub: &lt;a href="https://github.com/jufianto/blog-resource/tree/blog/queueprocess/exam-app-queue" rel="noopener noreferrer"&gt;jufianto/blog-resource/exam-app-queue&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Further Reading&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.nats.io/nats-concepts/jetstream" rel="noopener noreferrer"&gt;NATS JetStream docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.postgresql.org/docs/current/runtime-config-connection.html" rel="noopener noreferrer"&gt;PostgreSQL connection pooling&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://k6.io/docs/" rel="noopener noreferrer"&gt;k6 load testing&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Have you dealt with database bottlenecks under load? I'd like to hear about it.&lt;/p&gt;

</description>
      <category>go</category>
      <category>postgres</category>
      <category>architecture</category>
      <category>performance</category>
    </item>
    <item>
      <title>another of my blog, check it out.</title>
      <dc:creator>Jufianto Henri</dc:creator>
      <pubDate>Thu, 03 Apr 2025 09:09:51 +0000</pubDate>
      <link>https://dev.to/jufianto/another-of-my-blog-check-it-out-13dl</link>
      <guid>https://dev.to/jufianto/another-of-my-blog-check-it-out-13dl</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/jufianto/fixing-select2-issues-in-laravel-livewire-3-a-frustrating-but-solvable-challenge-194o" class="crayons-story__hidden-navigation-link"&gt;Fixing Select2 Issues in Laravel Livewire 3: A Frustrating but Solvable Challenge&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&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="/jufianto" 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%2F710116%2F23324c26-72a8-4fbf-8945-a37ac422ed34.jpeg" alt="jufianto profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/jufianto" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Jufianto Henri
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Jufianto Henri
                
              
              &lt;div id="story-author-preview-content-2008270" 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="/jufianto" 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%2F710116%2F23324c26-72a8-4fbf-8945-a37ac422ed34.jpeg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Jufianto Henri&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/jufianto/fixing-select2-issues-in-laravel-livewire-3-a-frustrating-but-solvable-challenge-194o" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Apr 3 '25&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/jufianto/fixing-select2-issues-in-laravel-livewire-3-a-frustrating-but-solvable-challenge-194o" id="article-link-2008270"&gt;
          Fixing Select2 Issues in Laravel Livewire 3: A Frustrating but Solvable Challenge
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/laravel"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;laravel&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/php"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;php&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/livewire"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;livewire&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/webdev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;webdev&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/jufianto/fixing-select2-issues-in-laravel-livewire-3-a-frustrating-but-solvable-challenge-194o" 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="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;4&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/jufianto/fixing-select2-issues-in-laravel-livewire-3-a-frustrating-but-solvable-challenge-194o#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;
            4 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>
      <category>laravel</category>
      <category>php</category>
      <category>livewire</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Fixing Select2 Issues in Laravel Livewire 3: A Frustrating but Solvable Challenge</title>
      <dc:creator>Jufianto Henri</dc:creator>
      <pubDate>Thu, 03 Apr 2025 08:45:08 +0000</pubDate>
      <link>https://dev.to/jufianto/fixing-select2-issues-in-laravel-livewire-3-a-frustrating-but-solvable-challenge-194o</link>
      <guid>https://dev.to/jufianto/fixing-select2-issues-in-laravel-livewire-3-a-frustrating-but-solvable-challenge-194o</guid>
      <description>&lt;p&gt;For the past couple of months, I've been working on building a simple CMS web app using &lt;strong&gt;Laravel&lt;/strong&gt; with &lt;strong&gt;Livewire 3&lt;/strong&gt;. While everything was going smoothly, I encountered an issue that left me frustrated—my &lt;strong&gt;Select2 dropdown wasn't updating or binding data correctly in Livewire&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  📌 Why Use Select2?
&lt;/h2&gt;

&lt;p&gt;I chose &lt;strong&gt;Select2&lt;/strong&gt; because I needed a simple UI component for searching through a list of data within a dropdown. Select2 provides an elegant solution that enhances standard &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; elements with search functionality, without requiring me to build a custom UI from scratch.&lt;/p&gt;

&lt;p&gt;However, integrating &lt;strong&gt;Select2&lt;/strong&gt; with &lt;strong&gt;Livewire 3&lt;/strong&gt; wasn’t as straightforward as I expected. The problem? &lt;strong&gt;Livewire doesn’t automatically recognize updates made by JavaScript-based components like Select2.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🚨 The Issue: Select2 and Livewire Data Binding
&lt;/h2&gt;

&lt;p&gt;When using &lt;strong&gt;Livewire&lt;/strong&gt;, form inputs are usually bound using &lt;code&gt;wire:model&lt;/code&gt;, allowing real-time updates to the component state. However, since &lt;strong&gt;Select2 manipulates the DOM using JavaScript&lt;/strong&gt;, Livewire doesn’t detect changes made by Select2 unless explicitly notified.&lt;/p&gt;

&lt;p&gt;here my basic setup&lt;/p&gt;

&lt;h3&gt;
  
  
  Blade Component (example.blade.php)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;
&lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"max-w-sm mx-auto mb-5"&lt;/span&gt; &lt;span class="na"&gt;wire:submit.prevent=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"countries"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"block mb-2 text-sm font-medium text-gray-900 dark:text-white"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Select an option&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;select&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"countries"&lt;/span&gt; &lt;span class="na"&gt;wire:model.live=&lt;/span&gt;&lt;span class="s"&gt;"select_value"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;selected&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Choose a country&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"US"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;United States&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"CA"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Canada&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"FR"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;France&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"DE"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Germany&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/select&amp;gt;&lt;/span&gt;

        &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"mt-2 block mb-2"&lt;/span&gt; &lt;span class="na"&gt;wire:model=&lt;/span&gt;&lt;span class="s"&gt;"select_value"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

        &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-white bg-blue-700 px-5 py-2 rounded-md"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Save&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;


&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;init_select2&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;ctr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#countries&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nx"&gt;ctr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select2&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;ready&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
        &lt;span class="c1"&gt;// init_select2();&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Livewire Component (Example.php)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;App\Livewire&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Livewire\Component&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Example&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Component&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nv"&gt;$select_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"default-value"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'livewire.example'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;submit&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
        &lt;span class="nf"&gt;dd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;select_value&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;p&gt;to be able use select2 and jquery, you must include this section on your blade layout&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css"&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the code above I do comment on section init select2 and select2 should not be active or running. &lt;br&gt;
here the expected result I need and this is without use select2 &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%2Fwmg40a21s1ouotb2zmso.gif" 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%2Fwmg40a21s1ouotb2zmso.gif" alt="expected result without select2" width="720" height="487"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;you see after click &lt;code&gt;save&lt;/code&gt; button I can see result the value I selected. lets turn on and init select2 by uncomment &lt;code&gt;init_select2();&lt;/code&gt;&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%2Fimxcvfy748nnlj7ov4ju.gif" 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%2Fimxcvfy748nnlj7ov4ju.gif" alt="failed result binding" width="720" height="487"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;you can see the result still &lt;code&gt;default-value&lt;/code&gt; and not binding based on value select we are selected.&lt;/p&gt;




&lt;h2&gt;
  
  
  ✅ The Solution: Manually Dispatching Events to Livewire
&lt;/h2&gt;

&lt;p&gt;Since &lt;strong&gt;Livewire 3&lt;/strong&gt; doesn’t automatically detect DOM changes from &lt;strong&gt;JavaScript-based UI components&lt;/strong&gt;, we need to manually update &lt;strong&gt;Livewire’s state&lt;/strong&gt; when &lt;strong&gt;Select2&lt;/strong&gt; changes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Livewire Component (Example.php)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;App\Livewire&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Livewire\Attributes\On&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Livewire\Component&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Example&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Component&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nv"&gt;$select_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"default-value"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'livewire.example'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;submit&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
        &lt;span class="nf"&gt;dd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;select_value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="na"&gt;#[On('select-updated')]&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;updateValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$val&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;select_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$val&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"update-value"&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;h3&gt;
  
  
  Blade Componenet (example.blade.php
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"max-w-sm mx-auto mb-5"&lt;/span&gt; &lt;span class="na"&gt;wire:submit.prevent=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"countries"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"block mb-2 text-sm font-medium text-gray-900 dark:text-white"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Select an option&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;select&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"countries"&lt;/span&gt; &lt;span class="na"&gt;wire:model=&lt;/span&gt;&lt;span class="s"&gt;"select_value"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;selected&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Choose a country&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"US"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;United States&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"CA"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Canada&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"FR"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;France&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"DE"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Germany&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/select&amp;gt;&lt;/span&gt;

        &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"mt-2 block mb-2"&lt;/span&gt; &lt;span class="na"&gt;wire:model=&lt;/span&gt;&lt;span class="s"&gt;"select_value"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

        &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"block text-sm mb-2"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;value selected: {{ $select_value }}&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

        &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-white bg-blue-700 px-5 py-2 rounded-md"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Save&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;

    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;init_select2&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;ctr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#countries&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nx"&gt;ctr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select2&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;ready&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
        &lt;span class="nf"&gt;init_select2&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#countries&lt;/span&gt;&lt;span class="dl"&gt;'&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="s2"&gt;change&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
            &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Livewire&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;select-updated&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;val&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;span class="nx"&gt;Livewire&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="s2"&gt;update-value&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
        &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;init_select2&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;event udpated and reset select2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

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

&lt;/div&gt;






&lt;h2&gt;
  
  
  🔍 &lt;strong&gt;Key Fixes &amp;amp; Takeaways&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;✅ &lt;strong&gt;Manually dispatch the &lt;code&gt;select-updated&lt;/code&gt; event&lt;/strong&gt; when Select2 changes.&lt;br&gt;
✅ &lt;strong&gt;Listen for &lt;code&gt;update-value&lt;/code&gt; in Livewire&lt;/strong&gt; to trigger a reinitialization of Select2.&lt;br&gt;
✅ &lt;strong&gt;Use &lt;code&gt;setTimeout(init_select2, 0);&lt;/code&gt;&lt;/strong&gt; to prevent Select2 from breaking after a Livewire re-render. &lt;code&gt;setTimeout&lt;/code&gt; is needed because it ensures that Livewire processes its updates first before re-initializing Select2.&lt;/p&gt;

&lt;p&gt;Now, every time a user selects an option, &lt;strong&gt;Livewire correctly updates its state&lt;/strong&gt;, and &lt;strong&gt;Select2 remains functional&lt;/strong&gt; after re-renders! 🚀&lt;/p&gt;

&lt;p&gt;here the result&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%2F2up0ljqma3trtg4ozvsg.gif" 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%2F2up0ljqma3trtg4ozvsg.gif" alt="final result" width="720" height="487"&gt;&lt;/a&gt;&lt;/p&gt;




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

&lt;p&gt;Integrating &lt;strong&gt;Select2&lt;/strong&gt; with &lt;strong&gt;Livewire 3&lt;/strong&gt; can be frustrating, but the solution is &lt;strong&gt;simple once you understand how Livewire handles JavaScript-based components&lt;/strong&gt;. By manually dispatching updates and re-initializing Select2, you can enjoy the benefits of &lt;strong&gt;Livewire’s reactivity&lt;/strong&gt; and &lt;strong&gt;Select2’s powerful search features&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you run into issues, try this approach and let me know how it works for you! 🚀🔥&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>php</category>
      <category>livewire</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Init your golang gRPC Services</title>
      <dc:creator>Jufianto Henri</dc:creator>
      <pubDate>Sat, 09 Nov 2024 14:58:22 +0000</pubDate>
      <link>https://dev.to/jufianto/init-your-golang-grpc-services-2g0l</link>
      <guid>https://dev.to/jufianto/init-your-golang-grpc-services-2g0l</guid>
      <description>&lt;p&gt;Hello, After so long time I'm not writing again (&lt;a href="https://medium.com/jufi-blogs/install-aplikasimu-dengan-docker-d434e902400e" rel="noopener noreferrer"&gt;last time write on medium&lt;/a&gt;), finally I do gather the intention to make an article again. today I want to share how do I creating my grpc services from stracth. &lt;/p&gt;

&lt;p&gt;for the context I want to create continues article, I will try to build complex system application that will mock like real world problem. but lets see later if I can complete that.&lt;/p&gt;

&lt;p&gt;for now lets do focus on how to creating the golang grpc services, I will create really simple application and how to test it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Install the prerequisites tools
&lt;/h3&gt;

&lt;p&gt;you need to install protoc first, I used linux so to install that need to run&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="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; protobuf-compiler  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;how if I use macos? run this, but I'm not sure if its work because I dont have macos&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;protobuf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;if already installed, please verify by run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;protoc &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;it will show the version of protoc, for me I have protoc version &lt;code&gt;libprotoc 3.6.1&lt;/code&gt;.&lt;br&gt;
after do that, install the requirement plugin protoc for golang&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go &lt;span class="nb"&gt;install &lt;/span&gt;google.golang.org/protobuf/cmd/protoc-gen-go@latest
go &lt;span class="nb"&gt;install &lt;/span&gt;google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and make sure bin for &lt;code&gt;protoc-gen-go&lt;/code&gt; and &lt;code&gt;protoc-gen-go-grpc&lt;/code&gt; already on your path.&lt;/p&gt;

&lt;h3&gt;
  
  
  Path Structure
&lt;/h3&gt;

&lt;p&gt;so this is my structure my project, btw this path structure will look like complicated, because I want to make continues app later in this project, so just bear with it&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%2Fnd7r9fcocx5svakv9vpl.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%2Fnd7r9fcocx5svakv9vpl.png" alt="Tree Folder" width="305" height="228"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;little breakdawn what inside the folder.&lt;br&gt;
&lt;code&gt;agent&lt;/code&gt; -&amp;gt; it will the base applications. basically I want to make app using state-machine pattern&lt;br&gt;
&lt;code&gt;agent/client&lt;/code&gt; -&amp;gt; it will hold the client type and the handler for GRPC&lt;br&gt;
&lt;code&gt;proto&lt;/code&gt; -&amp;gt; this will based proto files for our grpc. the files &lt;code&gt;*.pb.go&lt;/code&gt; and &lt;code&gt;*_grpc.pb.go&lt;/code&gt; will generated automaticall, we just need to write &lt;code&gt;.proto&lt;/code&gt; files for service definition of rpc&lt;/p&gt;
&lt;h3&gt;
  
  
  Make your syntax proto
&lt;/h3&gt;

&lt;p&gt;Lets make your syntax proto&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;proto/agent.proto&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;syntax = "proto3";
option go_package = "github.com/jufianto/state-agent/agentsrv-proto";

enum TaskStatus{
    UNKNOWN = 0;
    PROCESSING = 1;
    FAILED = 2;
    SUCCESS = 3;
}

message TaskRequest{
    string task_id = 1;
    string task_name = 2;
    string task_url = 3;
}

message TaskResponse{
    string task_id = 1;
    string task_result = 2;
    TaskStatus task_status = 3;

}

message TaskListResponse{
    repeated TaskResponse tasks = 1;
}

message TaskListRequest{
    repeated string tasks_id = 1;
}

message TaskNotify{
    string task_id = 1;
    TaskStatus task_status = 2;
}

message TaskStatusRequest {
    string task_id = 1;
}

message TasksStatusResponse {
    string task_id = 1;
    TaskStatus task_status = 2;
}

service TaskService{
    rpc CreateTask(TaskRequest) returns (TaskResponse) {}
    rpc ListTask(TaskListRequest) returns (TaskListResponse) {}
    rpc StatusTask(TaskStatusRequest) returns (TasksStatusResponse){}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;what happen on that code? &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;option go_package&lt;/code&gt; will be result as your package grpc after &lt;code&gt;.go&lt;/code&gt; files generated&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;enum&lt;/code&gt; is the type enum of &lt;code&gt;TaskStatus&lt;/code&gt; will be
&lt;code&gt;message&lt;/code&gt; will be like the &lt;code&gt;type struct&lt;/code&gt; on golang&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;string task_id = 1;&lt;/code&gt; is explain the type data of &lt;code&gt;task_id&lt;/code&gt; is string and the number should be consistent on the field. the number is need to identify the binary serialize later. so if you want later to add new field, you must not to change the the number on the field, just add it. it can break the backward compability when deserialize later.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;service TaskService&lt;/code&gt; is the defined of service grpc&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;after you coded that, lets go to folder &lt;code&gt;proto&lt;/code&gt; and execute this command to generate the grpc code go&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; protoc --go_out=. --go_opt=paths=source_relative \
    --go-grpc_out=. --go-grpc_opt=paths=source_relative \
*.proto

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

&lt;/div&gt;



&lt;p&gt;and you will see the result on &lt;code&gt;proto&lt;/code&gt; folder have 2 files&lt;br&gt;
&lt;code&gt;agent.pb.go&lt;/code&gt; -&amp;gt; the Go struct definitions for messages proto, It also includes methods to serialize/deserialize (marshal/unmarshal) the messages to/from binary or JSON formats.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;agent_grpc.ob.go&lt;/code&gt;. -&amp;gt; contains the grpc specific code, like the server / client definitions and also list of method / services grpc&lt;/p&gt;
&lt;h2&gt;
  
  
  Lets do the real code
&lt;/h2&gt;

&lt;p&gt;after generated the grpc code, create files &lt;code&gt;client.go&lt;/code&gt; on folder client and fill with this code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;client.go&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;
&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;agentsrv_proto&lt;/span&gt; &lt;span class="s"&gt;"github.com/jufianto/state-agent/proto"&lt;/span&gt;
    &lt;span class="s"&gt;"google.golang.org/grpc"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;AgentService&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Key&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;agentsrv_proto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UnimplementedTaskServiceServer&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;TaskResult&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;TaskID&lt;/span&gt;     &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;TaskResult&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;TaskStatus&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;NewAgentClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;AgentService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;AgentService&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;key&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;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;AgentService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;RegisterGW&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;srvGrpc&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;grpc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Server&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;agentsrv_proto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RegisterTaskServiceServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;srvGrpc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&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;p&gt;and also code the &lt;code&gt;handler.go&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;handler.go&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;AgentService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;CreateTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;agentsrv_proto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TaskRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;agentsrv_proto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TaskResponse&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"got request %+v &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;agentsrv_proto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TaskResponse&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;TaskId&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;     &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TaskId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;TaskResult&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"waiting for processing"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;TaskStatus&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;agentsrv_proto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TaskStatus_PROCESSING&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;AgentService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;ListTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;agentsrv_proto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TaskListRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;agentsrv_proto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TaskListResponse&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"list tasks"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetTasksId&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"not yet implemented"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;AgentService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;StatusTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;agentsrv_proto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TaskStatusRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;agentsrv_proto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TasksStatusResponse&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"status tasks"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetTaskId&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"not yet implemented"&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;p&gt;&lt;strong&gt;what happen on that code?&lt;/strong&gt; &lt;br&gt;
so, client.go it the base client for our primary services, it will hold the &lt;code&gt;agentsrv_proto.UnimplementedTaskServiceServer&lt;/code&gt; interface to make sure the handler will implemented the services grpc.&lt;/p&gt;

&lt;p&gt;the real thing gRPC is coming from this code &lt;code&gt;agentsrv_proto.RegisterTaskServiceServer(srvGrpc, a)&lt;/code&gt; it will make the grpc server registered on this handler and can be used later as grpc services.&lt;/p&gt;

&lt;p&gt;and for the &lt;code&gt;handler.go&lt;/code&gt; it will impelented from grpc generated code from the rpc we defined on protofiles. on the proto files, you can see you have rpc services look like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    rpc CreateTask(TaskRequest) returns (TaskResponse) {}
    rpc ListTask(TaskListRequest) returns (TaskListResponse) {}
    rpc StatusTask(TaskStatusRequest) returns (TasksStatusResponse){}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and all of this method grpc need to be implemented as you can see from the &lt;code&gt;handler.go&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;Finally, lets write the &lt;code&gt;main.go&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;main.go&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;
&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"log"&lt;/span&gt;
    &lt;span class="s"&gt;"net"&lt;/span&gt;

    &lt;span class="s"&gt;"github.com/jufianto/state-agent/agent/client"&lt;/span&gt;

    &lt;span class="s"&gt;"google.golang.org/grpc"&lt;/span&gt;
    &lt;span class="s"&gt;"google.golang.org/grpc/reflection"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="n"&gt;srvGrpc&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;grpc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewServer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;srv&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewAgentClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"key123"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;srv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RegisterGW&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;srvGrpc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"service listening...."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;net&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;net&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"tcp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;":3333"&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;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatalf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"failed to register grpc: %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;reflection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;srvGrpc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;srvGrpc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Serve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;net&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;p&gt;&lt;code&gt;srvGrpc := grpc.NewServer()&lt;/code&gt; will be init the grpc server, and &lt;code&gt;srv.RegisterGW&lt;/code&gt; will be registered the handler to server grpc and finally do serve on &lt;code&gt;srvGrpc.Serve(net)&lt;/code&gt; with port 3333&lt;/p&gt;

&lt;p&gt;&lt;code&gt;reflection.Register(srvGrpc)&lt;/code&gt; it just for helper to check what all the services on grpc services.&lt;/p&gt;

&lt;h3&gt;
  
  
  Run your services
&lt;/h3&gt;

&lt;p&gt;to run your services, please do run &lt;br&gt;
&lt;code&gt;go run agent/main.go&lt;/code&gt; and it will looks like &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%2F68hxe06lsfvu4v2y5r3n.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%2F68hxe06lsfvu4v2y5r3n.png" alt="Running Services" width="237" height="97"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;and you need to test it by postman&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%2Fn3uhxc8yyxcaavuqbvpl.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%2Fn3uhxc8yyxcaavuqbvpl.png" alt="Test Postman" width="800" height="319"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;you can see from the list down on postman, there have option list &lt;code&gt;Create Task, ListTask&lt;/code&gt;, thats the use of reflection package. it will help us to check what all the method on the gRPC services.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;Q: usually on Rest API services, I see there have routing that help route the services based on the path we called. but Why I dont see on here? &lt;br&gt;
A: that's the magic of grpc, basically its not based on routing but based on the method implemented. the method handler it should be same with the method we defined on the grpc generated code or can be simplified based on the proto rpc services defined.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/jufianto/grpc-learning-blog" rel="noopener noreferrer"&gt;Github Repo&lt;/a&gt; for this Projects &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;[!NOTE]&lt;br&gt;
if you have anything to ask please reach me on twitter and if you confuse with my bad writing you also can comment&lt;br&gt;
and all of this explanation based my experience, so feel free to correct me if I share the miss information&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;twitter: &lt;a href="https://x.com/jufiantohenri" rel="noopener noreferrer"&gt;https://x.com/jufiantohenri&lt;/a&gt;&lt;br&gt;
linkedin: &lt;a href="https://www.linkedin.com/in/jufianto/" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/jufianto/&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
