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


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>“ALWAYS serial” requirement sounds like an ideal case for a GenServer.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="253691" 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/best-way-to-schedule-events-in-elixir/48413/12">Post #11</a>
	                </div>
	            </div>
              <div id="likers-container-253691" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="253691"
                     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="253729" data-post-id="253729">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="kevinschweikert" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/kevinschweikert/120/26866_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  kevinschweikert
                    <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">
								<p>No, sorry, that isn’t what I meant. I’ll try it with an example:<br>
A user wants to schedule an event from 9 AM to 10 AM and then another one from 10 AM to 11 AM. Totally fine. But I don’t want to create an overlapping event from lets say 9:30 AM to 10:30 AM.<br>
But the more I think about it, I am convinced, that this isn’t the responsibility of Oban.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="253729" 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/best-way-to-schedule-events-in-elixir/48413/13">Post #12</a>
	                </div>
	            </div>
              <div id="likers-container-253729" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="253729"
                     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="253784" data-post-id="253784">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I haven’t implemented this, but I ran across this blog recently that demonstrates postgres functions to find overlapping meeting situations. Might be useful to you.</p>
<aside class="onebox allowlistedgeneric" data-onebox-src="https://hakibenita.com/postgresql-unknown-features#find-overlapping-ranges">
  <header class="source">
      <img src="https://hakibenita.com/images/favicon-32x32.png" class="site-icon" alt="" width="32" height="32">

      <a href="https://hakibenita.com/postgresql-unknown-features#find-overlapping-ranges" target="_blank" rel="noopener nofollow ugc">hakibenita.com</a>
  </header>

  <article class="onebox-body">
    <div class="aspect-image" style="--aspect-ratio:272/350;"><img src="https://hakibenita.com/images/00-postgresql-unknown-features.png" class="thumbnail" alt="" width="272" height="350"></div>

<h3><a href="https://hakibenita.com/postgresql-unknown-features#find-overlapping-ranges" target="_blank" rel="noopener nofollow ugc">Find Overlapping Ranges - Lesser Known PostgreSQL Features</a></h3>

  <p>In 2006 Microsoft conducted a customer survey to find what new features users want in new versions of Microsoft Office. To their surprise, more than 90% of what users asked for already existed, they just didn't know about it. To address the...</p>


  </article>

  <div class="onebox-metadata">
    
    
  </div>

  <div style="clear: both"></div>
</aside>
 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="253784" data-batch-url="/posts/batch_likers">
                        3
                      </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/best-way-to-schedule-events-in-elixir/48413/14">Post #13</a>
	                </div>
	            </div>
              <div id="likers-container-253784" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="253784"
                     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="253800" data-post-id="253800">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="kevinschweikert" data-post="13" data-topic="48413">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/kevinschweikert/48/26866_2.png" class="avatar"> kevinschweikert:</div>
<blockquote>
<p>A user wants to schedule an event from 9 AM to 10 AM and then another one from 10 AM to 11 AM. Totally fine. But I don’t want to create an overlapping event from lets say 9:30 AM to 10:30 AM.</p>
</blockquote>
</aside>
<p>You could enforce it in Postgres using range type and constraint.</p>
<p>In that case you would model your event with an <code>events</code> table that would have a <code>duration</code> column of <code>tsrange</code> or <code>timerange</code> type - the values would be <code>'[09:30, 10:30]'::timerange</code> or <code>'[2022-06-20 09:30, 2022-06-20 10:30]'::tsrange</code> depending on your needs.</p>
<p>And then you could create a non-overlapping constraint on that column, like in the example:</p><aside class="onebox allowlistedgeneric" data-onebox-src="https://www.postgresql.org/docs/current/rangetypes.html#RANGETYPES-CONSTRAINT">
  <header class="source">
      <img src="https://www.postgresql.org/favicon.ico" class="site-icon" alt="" width="48" height="48">

      <a href="https://www.postgresql.org/docs/current/rangetypes.html#RANGETYPES-CONSTRAINT" target="_blank" rel="noopener nofollow ugc" title="01:09PM - 14 May 2026">PostgreSQL Documentation – 14 May 26</a>
  </header>

  <article class="onebox-body">
    <div class="aspect-image" style="--aspect-ratio:540/557;"><img src="https://www.postgresql.org/media/img/about/press/elephant.png" class="thumbnail" alt="" width="540" height="557"></div>

<h3><a href="https://www.postgresql.org/docs/current/rangetypes.html#RANGETYPES-CONSTRAINT" target="_blank" rel="noopener nofollow ugc">UNIQUE - 8.17.&nbsp;Range Types</a></h3>

  <p>Range types are data types representing a range of values of some element type (called the range's subtype). For instance, ranges of timestamp might be used to represent the ranges of time that a meeting room is reserved. In this case the data type...</p>


  </article>

  <div class="onebox-metadata">
    
    
  </div>

  <div style="clear: both"></div>
</aside>
 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="253800" 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/best-way-to-schedule-events-in-elixir/48413/15">Post #14</a>
	                </div>
	            </div>
              <div id="likers-container-253800" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="253800"
                     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="253840" data-post-id="253840">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>You can probably use the :unique option, but it could wind up being kludgy.  I found :unique very handy for emails - to avoid duplicates. I think I would use ecto to model it and create a function that checks for overlapping events and schedules the oban job only if you get a valid changeset. Then you can encapsulate all that validation into the model. Probably want the check and update in a multi.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="253840" 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/best-way-to-schedule-events-in-elixir/48413/16">Post #15</a>
	                </div>
	            </div>
              <div id="likers-container-253840" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="253840"
                     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="254836" data-post-id="254836">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="sergio" data-post="10" data-topic="48413">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/sergio/48/26966_2.png" class="avatar"> sergio:</div>
<blockquote>
<p>I recommend not wasting your time building an infinitely scalable solution today.</p>
</blockquote>
</aside>
<p>Well, the whole idea spawned from making a serverless background job system that could work for my day job. The notion being that if it works for our use case, it could work for <em>anyone</em>.</p>
<p>I’m a huge fan of Faktory. It’s a polyglot background job system that is totally free (including a nice UI). And it’s based on Redis, which has an extremely high performance ceiling.</p>
<p>The downside to Faktory (or Resque or Sidekiq) is hosting your own instance, monitoring that instance, setting up alerting, etc etc.</p>
<p>I’ve personally longed for a serverless version of these products by the 5th time our Redis instance blew out and our product came to a screeching halt. I think it’s possible, depending on how motivated someone is to make it.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="254836" 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/best-way-to-schedule-events-in-elixir/48413/17">Post #16</a>
	                </div>
	            </div>
              <div id="likers-container-254836" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="254836"
                     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="254850" data-post-id="254850">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>PostgreSQL can only do this effectively due to a special type of locking system (Advisory Locks) that is dramatically more efficient for this particular use case.</p>
<p>The first place I ever remember seeing the technique was a Ruby Queue called Que. <a href="https://github.com/que-rb/que" class="inline-onebox" rel="noopener nofollow ugc">GitHub - que-rb/que: A Ruby job queue that uses PostgreSQL's advisory locks for speed and reliability. · GitHub</a></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="254850" 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/best-way-to-schedule-events-in-elixir/48413/18">Post #17</a>
	                </div>
	            </div>
              <div id="likers-container-254850" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="254850"
                     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="254852" data-post-id="254852">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I’m a huge fan of advisory locks! We use them frequently with Sidekiq/Resque/Faktory, as well as in web requests… <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>We also make use of other awesome Postgres features like jsonb columns and logical decoding of replication for CDC purposes. Postgres is an amazing piece of tech. Our product has 19 Postgres instances and not wimpy ones either; we love Postgres!</p>
<p>I’ve never tested Postgres’ advisory locks for the “high contention consumer” problem; I just assumed it would break down because it’s a very difficult problem… and Postgres has broken down for us in other ways.</p>
<p>We tried both Etcd and Redis for distributed locks and even Etcd went into completely unrecoverable states. Hell, even Redis Cluster has issues, hence why we just went with propriety AWS MemoryDB.</p>
<p>Distributed computing is hard.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="254852" 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/best-way-to-schedule-events-in-elixir/48413/19">Post #18</a>
	                </div>
	            </div>
              <div id="likers-container-254852" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="254852"
                     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="254894" data-post-id="254894">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I always assume that if I have system that manages to outgrow Oban, the next move to optimize would be Broadway.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="254894" 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/best-way-to-schedule-events-in-elixir/48413/20">Post #19</a>
	                </div>
	            </div>
              <div id="likers-container-254894" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="254894"
                     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="254920" data-post-id="254920">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="sorentwo" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/sorentwo/120/37360_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  sorentwo
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Oban Core Team</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>The feature that makes Postgres an efficient queue processor is <code>FOR UPDATE SKIP LOCKED</code>, which eliminates <code>SELECT</code> contention and doesn’t make use of advisory locks.</p>
<p>Long-held advisory locks don’t play well with Ecto because of how it uses pools. Advisory locks are owned by the connection that starts them, and they can only be released by the same connection. Add the fact that advisory locks don’t work with <code>pg_bouncer</code> in transaction or session pooling modes, and you’ll find that only the <code>xact</code> (transactional) variant is broadly useful for concurrency controls. That’s why Oban uses an unlogged table for <a href="https://hexdocs.pm/oban/Oban.Peers.Postgres.html" rel="noopener nofollow ugc">centralized leadership</a>.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="254920" data-batch-url="/posts/batch_likers">
                        4
                      </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/best-way-to-schedule-events-in-elixir/48413/21">Post #20</a>
	                </div>
	            </div>
              <div id="likers-container-254920" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="254920"
                     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/48413/load_more?page=3">Load more posts (7 remaining)</a>
</div></template></turbo-stream>