<turbo-stream action="append" target="posts_list"><template>    <div class="postbit" id="370659" data-post-id="370659">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="MarthinL" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  MarthinL
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="garrison" data-post="11" data-topic="71933">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/g/3bc359/48.png" class="avatar"> garrison:</div>
<blockquote>
<p>Alternatively you can cache the results of the queries in such a way that reading them again shortly afterwards is cheap. Any cache solution will do (a simple ets table would be my starting point, or maybe Cachex).</p>
<p>If you’re caching locally on the node (which is much easier) then you probably want to configure the load balancer to be sticky so that the clients end up on the same node both times.</p>
</blockquote>
</aside>
<p>All fair and true once I get there, but I really haven’t pieced together the most crucial part, which is what exactly the sequence of requests, calls, messages and events are that result in the web-socket (I hear I should actually say Channel as the abstraction of either a web-socket or a long-poll setup depending on what the client and the network between can handle) connecting the JS in the client and the process in the server pod where the state is presented as the socket parameter to a variety of callback functions and event handlers that returns a modified version of it. I recognise that as gen_server style behaviour so I’m not overly confused by state as a parameter, but if the fact that the app runs across multiple clusters is in play in any way, manually or automagically, I need to know about it as basis for everything else I figure on doing.   It’s fine to say Elixir is designed to run on clusters and imply I shouldn’t overthink it and let the magic do its thing, but unfortunately that hadn’t worked out all that brilliantly for me of late so now I am compelled to figure out exactly what enables it. There ultimately has to be a difference between a single node BEAM and a cluster of BEAM nodes and part of my concern is the number of people calling BEAM clustering, being fully meshed, way too chatty, meaning network intensive, for its own good and certainly too much for WAN links to work.</p>
<p>I’m intent is to grow beyond a single cluster over WAN links so if I don’t know how the clustering gets involved if at all then I don’t stand a chance at all of keeping intra-cluster and inter-cluster comms separate, and that would be a costly mistake.</p>
<p>So, I have a proposal. Tell me if the following statements are 100% accurate and if not what adjustment they need to be accurate. Once we’ve agreed on what should be accurate, I shall go do my best to confirm that the behaviour I see matches that or bring you proof that it doesn’t.</p>
<ol>
<li>a LiveView page’s two renders does calls the same callbacks but as part of two very different algorithms.</li>
<li>the two versions build the same data in memory independent of the other which means they can run on different nodes without any coordination of communication between the nodes.</li>
<li>One of the processes dies as soon as the page content had been assembled and sent to the client despite being part of a LiveView setup.</li>
<li>The other process, aware of its role in the LiveView life cycle keeps the socket open (perhaps without even sending the rendered data) and waits for the js on the client to upgrade the socket to a web-socket or engages long poll.</li>
<li>once the socket is established the second version of the process listens for messages from the client in the socket, processes it using application callbacks to which it sends the assigns and other socket attributes derived during the duplicate startup processing as the socket parameter which serves as the state “variable”.</li>
<li>When the network layer changes the state of the socket itself, either because the connection was reset or terminated from the client side, the socket handler either participates in an attempted reconnection or closes the socket as well and abandon the state it had kept in memory.</li>
<li>When the js code detects a change in the socket state it attempts to reconnect, failing which it reports a problem and waits for the user to reload the page which re-initialises everything from scratch in a brand new session.</li>
</ol>
<p>It remains to be seen if that is accurate or not, but if it is, and from where I’m sitting right now, it appears to have been a rather trivial exercise to avoid the double render and associated double data loading and processing. Especially if the second copy doesn’t really send through the initially rendered content but only the subsequent deltas calculated from that. If that turns out to be true I will go reread the rationale in the lifecycle descriptions another thousand times to figure out what I missed that made it a bad idea to do the hard work only once.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="370659" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/clustered-liveview-app-web-socket/71933/12">Post #11</a>
	                </div>
	            </div>
              <div id="likers-container-370659" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="370659"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #11"></div>
  </section>
</div>
    <div class="postbit" id="370661" data-post-id="370661">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="rhcarvalho" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/rhcarvalho/120/32243_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  rhcarvalho
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I wanted to note another important fact about the LV architecture: you don’t get double mount/3 and double database queries and everything else all the time.</p>
<p>That only happens at the initial request entering a “live session”. Navigation (push_navigate and push_patch) within a live session (that you declare in router.ex) goes over the WebSocket connection, only sends minimal HTML diffs and in those cases mount/3 is called only once (and connected? would always return true in those cases).</p>
<p>You’re on the right track to piece everything together!</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="370661" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/clustered-liveview-app-web-socket/71933/13">Post #12</a>
	                </div>
	            </div>
              <div id="likers-container-370661" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="370661"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #12"></div>
  </section>
</div>
    <div class="postbit" id="370662" data-post-id="370662">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="garrison" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  garrison
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Just so we’re clear here, I am not a maintainer and I don’t have infinitely deep knowledge of LV internals. Maybe someone who is/has those things can comment, but it’s not me.</p>
<p>With that said, your understanding sounds mostly correct to me up to here:</p>
<aside class="quote no-group" data-username="MarthinL" data-post="12" data-topic="71933">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/m/3da27b/48.png" class="avatar"> MarthinL:</div>
<blockquote>
<p>the socket handler either participates in an attempted reconnection or closes the socket as well and abandon the state it had kept in memory</p>
</blockquote>
</aside>
<p>A <a href="https://en.wikipedia.org/wiki/WebSocket" rel="noopener nofollow ugc">WebSocket</a> is a TCP connection. TCP will attempt to retransmit lost packets to some degree, but if the connection fails I don’t <em>think</em> there is any further reconnect logic on the LiveView side.</p>
<p>I believe what would happen is the TCP connection would close, the LiveView process would die, and the LiveView <em>client</em> would attempt to reconnect and go through the entire mounting dance from the beginning. I’m not sure if the reconnect would result in two mounts or one, but my guess is it would be one (the socket connection) since you already have an HTML page loaded.</p>
<p>You should run some experiments and report back. I don’t think any of this is documented in full detail but it would be nice.</p>
<aside class="quote no-group" data-username="MarthinL" data-post="12" data-topic="71933">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/m/3da27b/48.png" class="avatar"> MarthinL:</div>
<blockquote>
<p>When the js code detects a change in the socket state it attempts to reconnect, failing which it reports a problem and waits for the user to reload the page which re-initialises everything from scratch in a brand new session</p>
</blockquote>
</aside>
<p>If the socket is down LV adds a CSS class to the page which can trigger display of a “reconnecting” message. What exactly is displayed is up to you, but there is a default in the generated layouts which is what you’re seeing.</p>
<p>I think the client just tries to reconnect. It’s not waiting for the user to do anything.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="370662" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/clustered-liveview-app-web-socket/71933/14">Post #13</a>
	                </div>
	            </div>
              <div id="likers-container-370662" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="370662"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #13"></div>
  </section>
</div>
    <div class="postbit" id="370667" data-post-id="370667">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="MarthinL" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  MarthinL
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="garrison" data-post="14" data-topic="71933">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/g/3bc359/48.png" class="avatar"> garrison:</div>
<blockquote>
<p>Just so we’re clear here, I am not a maintainer and I don’t have infinitely deep knowledge of LV internals. Maybe someone who is/has those things can comment, but it’s not me.</p>
</blockquote>
</aside>
<p>I know, that’s the trouble with forum discussions I suppose, and English. No distinction between you (singular, personally) and you (plural, collectively, or whomever the shoe fits). It’s too demanding if you <span class="mention">@ddresss</span> someone specific and if you don’t then eyes tend to glaze over as soon as the conversation gets a bit tricky. Thanks for staying engaged even when it’s outside your comfort zone.</p>
<aside class="quote no-group" data-username="garrison" data-post="14" data-topic="71933">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/g/3bc359/48.png" class="avatar"> garrison:</div>
<blockquote>
<p>A <a href="https://en.wikipedia.org/wiki/WebSocket" rel="noopener nofollow ugc">WebSocket</a> is a TCP connection</p>
</blockquote>
</aside>
<p>Agreed, which is a protocol that needs to be complied with and consequences when you don’t.  No harm, no foul. How to respond when the lower layers are done with a socket is an application layer question, so in this case what I meant was that there’s two possibilities. Either the demise of the socket leads to the entire LiveView session having to be set up from scratch with another server or the application layer repeats parts of what it does during setup to attempt to replace the broken socket with a new one. Seeing that the client side explicitly tries to reconnect I stated the assumption that the server side participates in reconnecting the socket to the same process if possible rather than tear everything down all every time and starting another process by default. I don’t know what the truth is,  but I am hoping someone does and is willing to tell me. I don’t even have an opinion about what the better way would be - rescuing the state in memory might seem the more noble approach but may be the worst idea because failing hard and early actually restores functionality the quickest and avoids a boatload of complicated rescue code that never gets fully battle tested or end up becoming part of “normal” without anyone noticing the failures it’s compensating for. You know, the age old argument about defensive programming  s failing as early as soon as any unexpected condition occur so the higher level code can try again with a clean state.</p>
<aside class="quote no-group" data-username="garrison" data-post="14" data-topic="71933">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/g/3bc359/48.png" class="avatar"> garrison:</div>
<blockquote>
<p>If the socket is down LV adds a CSS class to the page which can trigger display of a “reconnecting” message. What exactly is displayed is up to you, but there is a default in the generated layouts which is what you’re seeing.</p>
</blockquote>
</aside>
<p>Thanks for the confirmation but that is how I had it too.</p>
<aside class="quote no-group" data-username="garrison" data-post="14" data-topic="71933">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/g/3bc359/48.png" class="avatar"> garrison:</div>
<blockquote>
<p>I think the client just tries to reconnect. It’s not waiting for the user to do anything.</p>
</blockquote>
</aside>
<p>Yes, it tries to reconnect automatically, and often does when the session had been inactive or on a background tab for a long time, but that wasn’t the case I referred to. I was talking about the situation where the client-based reconnection times out, so fails. I’m not sure if it will keep trying periodically, how often or triggered by what, or if it would, once an attempt to reconnect has failed (timeout or error response) it gives up, displays the error and never try again unless the user reloads.  That seemed to be the behaviour I saw for myself and got user feedback about when my current load balancing arrangement results in the bad gateway errors.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="370667" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/clustered-liveview-app-web-socket/71933/15">Post #14</a>
	                </div>
	            </div>
              <div id="likers-container-370667" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="370667"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #14"></div>
  </section>
</div>
    <div class="postbit" id="370673" data-post-id="370673">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="MarthinL" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  MarthinL
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="MarthinL" data-post="12" data-topic="71933">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/m/3da27b/48.png" class="avatar"> MarthinL:</div>
<blockquote>
<p>It remains to be seen if that is accurate or not, but if it is, and from where I’m sitting right now, it appears to have been a rather trivial exercise to avoid the double render and associated double data loading and processing. Especially if the second copy doesn’t really send through the initially rendered content but only the subsequent deltas calculated from that. If that turns out to be true I will go reread the rationale in the lifecycle descriptions another thousand times to figure out what I missed that made it a bad idea to do the hard work only once.</p>
</blockquote>
</aside>
<p>I’d like to:</p>
<ol>
<li>clarify that this wasn’t meant as criticism, and</li>
<li>venture a guess as to why the double render approach won out.</li>
</ol>
<p>My guess is that it had to do with getting js code required to play its part in upgrading the socket ready for action in time. To get a socket the client first issues a regular get request and then asks that it gets upgraded to a socket. If the that initial get request is the standard request issued by the browser when you navigate to a url, it ultimately means that the code that needs to do the asking (for the upgrade) can only do that once it has arrived at the browser, which on high latency connections and big initial page loads could make it unrealistic to expect the code to activate in time to still catch the browser’s initial request in time to make the upgrade request on it. It was likely far more predictable if the original request was allowed to run its course to completion as per usual and then, once the js is in place, for it to issue its own, second or new get request it can reliably expect to get upgraded if the network allows for it.</p>
<p>If that is more or less true, it would mean a second get request will always be the safer option. But I am still curious about what would prevent the use the platform’s capabilities to see to it that the process responding to the second http get request can put the state variables it requires in order to service the socket the LiveView way from the work done by the original request. I understand the double work is only in play for new page requests, and maybe my sample is still a bit skewed, but it still seem to me those “initial” page loads happen often enough to consider alternatives.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="370673" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/clustered-liveview-app-web-socket/71933/16">Post #15</a>
	                </div>
	            </div>
              <div id="likers-container-370673" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="370673"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #15"></div>
  </section>
</div>
    <div class="postbit" id="370674" data-post-id="370674">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="garrison" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  garrison
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I am fairly confident the server does not hold on to any state after the socket closes due to disconnection. The client will receive a new server process when it reconnects. But there is always some chance I am wrong, at least in some edge case, and someone will come along and correct me. The nature of forums indeed <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p>
<p>As for the client, it will keep trying to reconnect for quite a while, maybe forever(?). Note that there is a bug in Firefox which causes an enormous backoff (like, a minute or two) to build up if the server is down for a few minutes. I’ve seen it discussed on here before.</p>
<p>The reason the double render exists, from what I understand, is that LiveView was originally an addon feature to Phoenix, a framework which already had routes and pipelines and so on. As time has gone on LiveView has become much more powerful, acquired much of that pipeline functionality for itself, and has become somewhat of a flagship feature. The double render is, essentially, tech debt. Hopefully someone will put the work in eventually to pay it off, but it won’t be easy and someone has to actually <em>do</em> that work. It would probably even mean breaking changes.</p>
<p>In hindsight having two request pipelines essentially glued together doing double the work is quite absurd. If you were designing everything from scratch you probably wouldn’t do that. But things are rarely designed from scratch!</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="370674" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/clustered-liveview-app-web-socket/71933/17">Post #16</a>
	                </div>
	            </div>
              <div id="likers-container-370674" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="370674"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #16"></div>
  </section>
</div>
    <div class="postbit" id="370675" data-post-id="370675">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="MarthinL" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  MarthinL
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="rhcarvalho" data-post="4" data-topic="71933">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/rhcarvalho/48/32243_2.png" class="avatar"> rhcarvalho:</div>
<blockquote>
<p>the server upgrades the connection gets to a WebSocket</p>
</blockquote>
</aside>
<p>Can you confirm that it’s the server that initiates the upgrade to socket, or is that done from the client side as I’ve been assuming until now?</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="370675" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/clustered-liveview-app-web-socket/71933/18">Post #17</a>
	                </div>
	            </div>
              <div id="likers-container-370675" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="370675"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #17"></div>
  </section>
</div>
    <div class="postbit" id="370701" data-post-id="370701">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="rhcarvalho" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/rhcarvalho/120/32243_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  rhcarvalho
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="rhcarvalho" data-post="4" data-topic="71933">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/rhcarvalho/48/32243_2.png" class="avatar"> rhcarvalho:</div>
<blockquote>
<p>the browser runs JS which connects the socket - it may land on any pod - the server upgrades the connection gets to a WebSocket and the LiveView process and state lives in this pod that served the second “connected” request.</p>
</blockquote>
</aside>
<p>The WebSocket connection always initiates on the client.<br>
Without JavaScript code in your <code>app.js</code>, there won’t be any WebSocket connection established.</p>
<p>The client requests that the connection is upgraded to a WebSocket, then the server needs to do their part in the protocol (including refusing the upgrade).</p>
<p>The above is agnostic to server technology, thus not specific to Elixir/Phoenix/LiveView.</p>
<p>Notes:</p>
<ul>
<li>Unless you’re serving client traffic directly from your BEAM-based web server, there are typically reverse proxies between clients and your server. That’s the case with Kubernetes, the case if you proxy traffic through Cloudflare, and many other possible setups. In those cases, it’s worth knowing that what you may think as one WS connection between client/browser and server/application is, in fact, 2 or more connections, as many as the number of hops between client and server. I say that because when you think about reconnections, it is worth considering those.</li>
<li>I think somewhere in this thread I saw the word “Channel”. WebSocket is just one of the options how to make LiveView (built on top of Phoenix Channels) work. The system is made to be transport-agnostic, and there is a Long Poll transport that ships out of the box, and that can be used when, for any reason, the client is unable to establish a WS connect. The intention to connect/reconnect and what transport mechanism to use is always initiated from the client/JS.</li>
</ul> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="370701" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/clustered-liveview-app-web-socket/71933/19">Post #18</a>
	                </div>
	            </div>
              <div id="likers-container-370701" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="370701"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #18"></div>
  </section>
</div>
    <div class="postbit" id="370704" data-post-id="370704">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="MarthinL" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  MarthinL
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="rhcarvalho" data-post="19" data-topic="71933">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/rhcarvalho/48/32243_2.png" class="avatar"> rhcarvalho:</div>
<blockquote>
<p>The WebSocket connection always initiates on the client.</p>
</blockquote>
</aside>
<p>Thanks, that’s how I understood it and why I got confused when you stated the server upgrades the connection to a socket. My understanding now being that it is requested by the client but the server has to agree and could decline.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="370704" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/clustered-liveview-app-web-socket/71933/20">Post #19</a>
	                </div>
	            </div>
              <div id="likers-container-370704" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="370704"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #19"></div>
  </section>
</div>
    <div class="postbit" id="371180" data-post-id="371180">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="Hermanverschooten" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/Hermanverschooten/120/6447_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  Hermanverschooten
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>The state of the initial mount is lost after the render completes, this is the same as a request to a controller.  The js then initiates the new request which will become the websocket connection managed by the liveview process on the server.  For recovery after a disconnect it will first build the initial state again in mount, then there is code that will resent the form content if any to update the state on the server.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="371180" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/clustered-liveview-app-web-socket/71933/21">Post #20</a>
	                </div>
	            </div>
              <div id="likers-container-371180" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="371180"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #20"></div>
  </section>
</div>
</template></turbo-stream><turbo-stream action="replace" target="load-more-container"><template><div id="load-more-container" class="load-more-container">
    <a class="load-more-button" data-turbo-stream="true" href="/topics/71933/load_more?page=3">Load more posts (8 remaining)</a>
</div></template></turbo-stream>