DEV Community: dbzero The latest articles on DEV Community by dbzero (@dbzero). https://dev.to/dbzero 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%2Forganization%2Fprofile_image%2F12074%2F22a4c96c-729d-4a03-a4d1-3e547edde8a1.png DEV Community: dbzero https://dev.to/dbzero en I Vibe‑Coded a Booking API—Then Made It Production‑Grade (Part 1) Wojciech Kozłowski Tue, 23 Dec 2025 15:29:50 +0000 https://dev.to/dbzero/i-vibe-coded-a-booking-api-then-made-it-production-grade-part-1-44h5 https://dev.to/dbzero/i-vibe-coded-a-booking-api-then-made-it-production-grade-part-1-44h5 <p>Booking operations are ubiquitous — we book flats, rooms, cars, appointments, and much more. Yet delivering a performant booking API can be deceptively tricky.</p> <p>My first attempt was naive: I asked an AI agent (Claude Opus 4.5) to design the data model and implementation end‑to‑end, with the only constraint being Python and FastAPI. The result looked plausible at first glance, but the code hid several serious flaws. Here’s one of them:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight python"><code> <span class="c1"># Get all properties in the city </span> <span class="n">properties_in_city</span> <span class="o">=</span> <span class="n">db</span><span class="p">.</span><span class="nf">query</span><span class="p">(</span><span class="n">Property</span><span class="p">).</span><span class="nf">filter</span><span class="p">(</span> <span class="n">Property</span><span class="p">.</span><span class="n">city</span><span class="p">.</span><span class="nf">ilike</span><span class="p">(</span><span class="sa">f</span><span class="sh">"</span><span class="s">%</span><span class="si">{</span><span class="n">city</span><span class="si">}</span><span class="s">%</span><span class="sh">"</span><span class="p">)</span> <span class="p">).</span><span class="nf">all</span><span class="p">()</span> <span class="c1"># Filter out properties with overlapping bookings </span> <span class="n">available_properties</span> <span class="o">=</span> <span class="p">[]</span> <span class="k">for</span> <span class="nb">property</span> <span class="ow">in</span> <span class="n">properties_in_city</span><span class="p">:</span> <span class="n">overlapping_bookings</span> <span class="o">=</span> <span class="n">db</span><span class="p">.</span><span class="nf">query</span><span class="p">(</span><span class="n">Booking</span><span class="p">).</span><span class="nf">filter</span><span class="p">(</span> <span class="nf">and_</span><span class="p">(</span> <span class="n">Booking</span><span class="p">.</span><span class="n">property_id</span> <span class="o">==</span> <span class="nb">property</span><span class="p">.</span><span class="nb">id</span><span class="p">,</span> <span class="n">Booking</span><span class="p">.</span><span class="n">start_date</span> <span class="o">&lt;</span> <span class="n">end_date</span><span class="p">,</span> <span class="n">Booking</span><span class="p">.</span><span class="n">end_date</span> <span class="o">&gt;</span> <span class="n">start_date</span> <span class="p">)</span> <span class="p">).</span><span class="nf">first</span><span class="p">()</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">overlapping_bookings</span><span class="p">:</span> <span class="n">available_properties</span><span class="p">.</span><span class="nf">append</span><span class="p">(</span><span class="nb">property</span><span class="p">)</span> <span class="k">return</span> <span class="n">available_properties</span> </code></pre> </div> <p>Two problems jump out:</p> <ul> <li>Using <code>ILIKE '%...%'</code> typically prevents index usage and often triggers a full table scan unless specialized indexing (e.g., trigram or full‑text) is in place.</li> <li>Worse, the availability check runs a separate query per property — a classic N+1 pattern that will be painfully slow at scale.</li> </ul> <h2> Start with abstractions </h2> <p>A better path is to describe the problem in abstract terms, separate from any domain specifics. What should a general‑purpose booking engine provide?</p> <p>Core primitives:</p> <ol> <li>Bookable entities (flats, cars, rooms, tables — any resource).</li> <li>Booking events with at least a start and end (date/time).</li> </ol> <p>Core operations:</p> <ol> <li>Retrieve bookable entities available within a given range.</li> <li>Create and cancel bookings (i.e., mark an entity as booked or free).</li> </ol> <p>After learning that Django’s abstract models might be a fit, I fed these requirements into an LLM. Here’s the result—let’s review it step by step.</p> <p>The booking event in the suggested model is represented by an abstract model class—it’s a simple container.<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight python"><code><span class="k">class</span> <span class="nc">AbstractBooking</span><span class="p">(</span><span class="n">models</span><span class="p">.</span><span class="n">Model</span><span class="p">):</span> <span class="n">start_time</span> <span class="o">=</span> <span class="n">models</span><span class="p">.</span><span class="nc">DateTimeField</span><span class="p">()</span> <span class="n">end_time</span> <span class="o">=</span> <span class="n">models</span><span class="p">.</span><span class="nc">DateTimeField</span><span class="p">()</span> <span class="c1"># flexible status field </span> <span class="n">is_active</span> <span class="o">=</span> <span class="n">models</span><span class="p">.</span><span class="nc">BooleanField</span><span class="p">(</span><span class="n">default</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span> <span class="k">class</span> <span class="nc">Meta</span><span class="p">:</span> <span class="n">abstract</span> <span class="o">=</span> <span class="bp">True</span> </code></pre> </div> <p>The QuerySet implements the availability search logic. It creates a statement that can be safely used as a filter without risking the N+1 problem that ORMs are notorious for.<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight python"><code><span class="k">class</span> <span class="nc">BookableQuerySet</span><span class="p">(</span><span class="n">models</span><span class="p">.</span><span class="n">QuerySet</span><span class="p">):</span> <span class="k">def</span> <span class="nf">available</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">start</span><span class="p">,</span> <span class="n">end</span><span class="p">,</span> <span class="n">booking_relation_name</span><span class="o">=</span><span class="sh">'</span><span class="s">bookings</span><span class="sh">'</span><span class="p">):</span> <span class="sh">"""</span><span class="s"> Excludes objects that have an active booking overlapping with the requested range. </span><span class="sh">"""</span> <span class="c1"># Define the overlap condition </span> <span class="n">overlap_condition</span> <span class="o">=</span> <span class="nc">Q</span><span class="p">(</span> <span class="o">**</span><span class="p">{</span><span class="sa">f</span><span class="sh">"</span><span class="si">{</span><span class="n">booking_relation_name</span><span class="si">}</span><span class="s">__start_time__lt</span><span class="sh">"</span><span class="p">:</span> <span class="n">end</span><span class="p">,</span> <span class="sa">f</span><span class="sh">"</span><span class="si">{</span><span class="n">booking_relation_name</span><span class="si">}</span><span class="s">__end_time__gt</span><span class="sh">"</span><span class="p">:</span> <span class="n">start</span><span class="p">,</span> <span class="sa">f</span><span class="sh">"</span><span class="si">{</span><span class="n">booking_relation_name</span><span class="si">}</span><span class="s">__is_active</span><span class="sh">"</span><span class="p">:</span> <span class="bp">True</span><span class="p">}</span> <span class="p">)</span> <span class="k">return</span> <span class="n">self</span><span class="p">.</span><span class="nf">exclude</span><span class="p">(</span><span class="n">overlap_condition</span><span class="p">)</span> </code></pre> </div> <p>Finally, the bookable mixin, which can make any future model bookable:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight python"><code><span class="k">class</span> <span class="nc">BookableMixin</span><span class="p">(</span><span class="n">models</span><span class="p">.</span><span class="n">Model</span><span class="p">):</span> <span class="n">objects</span> <span class="o">=</span> <span class="n">BookableQuerySet</span><span class="p">.</span><span class="nf">as_manager</span><span class="p">()</span> <span class="k">class</span> <span class="nc">Meta</span><span class="p">:</span> <span class="n">abstract</span> <span class="o">=</span> <span class="bp">True</span> <span class="k">def</span> <span class="nf">is_available</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">start</span><span class="p">,</span> <span class="n">end</span><span class="p">):</span> <span class="c1"># Check specific instance availability </span> <span class="c1"># Note: This requires the concrete model to define the reverse relation </span> <span class="k">return</span> <span class="ow">not</span> <span class="n">self</span><span class="p">.</span><span class="n">bookings</span><span class="p">.</span><span class="nf">filter</span><span class="p">(</span> <span class="n">start_time__lt</span><span class="o">=</span><span class="n">end</span><span class="p">,</span> <span class="n">end_time__gt</span><span class="o">=</span><span class="n">start</span><span class="p">,</span> <span class="n">is_active</span><span class="o">=</span><span class="bp">True</span> <span class="p">).</span><span class="nf">exists</span><span class="p">()</span> </code></pre> </div> <p>Looks fantastic, right? Not quite. There are a few major limitations that prevent this from being a truly foundational model.</p> <h3> Limitation 1 — Lack of composability </h3> <p>You cannot have a ForeignKey to an abstract model. Since an abstract model does not exist as a table, you cannot create a ForeignKey pointing to it. For example, if you want a separate "rating" model related to bookings, there’s no seamless way to attach it to the abstract base; you’d need GenericForeignKey (complex and slower) or duplicate foreign keys per concrete subtype.</p> <h3> Limitation 2 — Unable to query across child types easily </h3> <p>Because there is no single parent table, you cannot execute a simple query that spans all subtypes (e.g., “get all items ordered by created_at”). To list the 10 most recent items across <code>Flat</code> and <code>Room</code>, you must query each separately, merge in Python, and resort — awkward and inefficient.</p> <h3> Limitation 3 — Tight coupling </h3> <p>Without good composability, teams often drift toward the “God Object” anti‑pattern — stuffing logging, timestamps, status, validation, and more into one base class. That tight coupling makes unrelated changes risky.</p> <h2> Is there a better way? </h2> <p>What should a truly foundational model provide?</p> <ul> <li> <strong>Type‑agnostic</strong>: Don’t hard‑code date granularity; allow days, hours, or higher precision.</li> <li> <strong>Composability</strong>: Plug in other foundational concerns (ratings, comments) cleanly.</li> <li> <strong>True polymorphism</strong>: Operate uniformly over all bookable entities (Flats, Cars, Boats) where their shared features apply.</li> <li> <strong>Performance</strong> and <strong>scalability</strong>: Handle realistic loads efficiently and scale from single‑server to distributed deployments.</li> </ul> <p>Fortunately, with <code>dbzero</code> we’re no longer limited to traditional ORMs or SQL schemas. Here’s a foundational model that might meet the functional and technical requirements.<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight python"><code><span class="nd">@db0.memo</span> <span class="k">class</span> <span class="nc">BookingEvent</span><span class="p">:</span> <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">from_date</span><span class="p">,</span> <span class="n">to_date</span><span class="p">,</span> <span class="nb">object</span><span class="p">:</span> <span class="sh">'</span><span class="s">BookableResource</span><span class="sh">'</span><span class="p">,</span> <span class="n">owns_lock</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="bp">False</span><span class="p">):</span> <span class="n">self</span><span class="p">.</span><span class="n">from_date</span> <span class="o">=</span> <span class="n">from_date</span> <span class="n">self</span><span class="p">.</span><span class="n">to_date</span> <span class="o">=</span> <span class="n">to_date</span> <span class="n">self</span><span class="p">.</span><span class="nb">object</span> <span class="o">=</span> <span class="nb">object</span> <span class="n">self</span><span class="p">.</span><span class="n">owns_lock</span> <span class="o">=</span> <span class="n">owns_lock</span> </code></pre> </div> <p><code>BookingEvent</code> is minimal — a container that references the booked object plus a flag indicating whether the calendar currently owns the reservation lock.<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight python"><code><span class="nd">@db0.memo</span> <span class="k">class</span> <span class="nc">BookableResource</span><span class="p">:</span> <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="n">self</span><span class="p">):</span> <span class="c1"># Index for start times of locked events </span> <span class="n">self</span><span class="p">.</span><span class="n">__ix_locked_from</span> <span class="o">=</span> <span class="n">db0</span><span class="p">.</span><span class="nf">index</span><span class="p">()</span> <span class="c1"># Index for end times of locked events </span> <span class="n">self</span><span class="p">.</span><span class="n">__ix_locked_to</span> <span class="o">=</span> <span class="n">db0</span><span class="p">.</span><span class="nf">index</span><span class="p">()</span> <span class="k">def</span> <span class="nf">is_available</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">from_date</span><span class="p">:</span> <span class="n">Any</span><span class="p">,</span> <span class="n">to_date</span><span class="p">:</span> <span class="n">Any</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">bool</span><span class="p">:</span> <span class="c1"># Check for any overlapping bookings </span> <span class="n">overlapping</span> <span class="o">=</span> <span class="n">db0</span><span class="p">.</span><span class="nf">find</span><span class="p">(</span> <span class="n">self</span><span class="p">.</span><span class="n">__ix_locked_from</span><span class="p">.</span><span class="nf">select</span><span class="p">(</span><span class="bp">None</span><span class="p">,</span> <span class="n">to_date</span><span class="p">),</span> <span class="n">self</span><span class="p">.</span><span class="n">__ix_locked_to</span><span class="p">.</span><span class="nf">select</span><span class="p">(</span><span class="n">from_date</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span> <span class="p">)</span> <span class="k">return</span> <span class="ow">not</span> <span class="n">overlapping</span> <span class="k">def</span> <span class="nf">_add_lock</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">event</span><span class="p">:</span> <span class="sh">'</span><span class="s">BookingEvent</span><span class="sh">'</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="bp">None</span><span class="p">:</span> <span class="sh">"""</span><span class="s"> Add a lock for a booking event. </span><span class="sh">"""</span> <span class="n">self</span><span class="p">.</span><span class="n">__ix_locked_from</span><span class="p">.</span><span class="nf">add</span><span class="p">(</span><span class="n">event</span><span class="p">.</span><span class="n">from_date</span><span class="p">,</span> <span class="n">event</span><span class="p">)</span> <span class="n">self</span><span class="p">.</span><span class="n">__ix_locked_to</span><span class="p">.</span><span class="nf">add</span><span class="p">(</span><span class="n">event</span><span class="p">.</span><span class="n">to_date</span><span class="p">,</span> <span class="n">event</span><span class="p">)</span> <span class="k">def</span> <span class="nf">_remove_lock</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">event</span><span class="p">:</span> <span class="sh">'</span><span class="s">BookingEvent</span><span class="sh">'</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="bp">None</span><span class="p">:</span> <span class="sh">"""</span><span class="s"> Remove a lock for a booking event. </span><span class="sh">"""</span> <span class="n">self</span><span class="p">.</span><span class="n">__ix_locked_from</span><span class="p">.</span><span class="nf">remove</span><span class="p">(</span><span class="n">event</span><span class="p">.</span><span class="n">from_date</span><span class="p">,</span> <span class="n">event</span><span class="p">)</span> <span class="n">self</span><span class="p">.</span><span class="n">__ix_locked_to</span><span class="p">.</span><span class="nf">remove</span><span class="p">(</span><span class="n">event</span><span class="p">.</span><span class="n">to_date</span><span class="p">,</span> <span class="n">event</span><span class="p">)</span> </code></pre> </div> <p>This class maintains two indexes per object. Per‑object indexing in <code>dbzero</code> favors data locality and makes availability checks fast without scanning the whole world. It lets us check a specific object’s availability or retrieve its past/future bookings efficiently — an important scalability lever.</p> <p>About <code>is_available</code>:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight python"><code><span class="k">def</span> <span class="nf">is_available</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">from_date</span><span class="p">,</span> <span class="n">to_date</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">bool</span><span class="p">:</span> <span class="n">overlapping</span> <span class="o">=</span> <span class="n">db0</span><span class="p">.</span><span class="nf">find</span><span class="p">(</span> <span class="n">self</span><span class="p">.</span><span class="n">__ix_locked_from</span><span class="p">.</span><span class="nf">select</span><span class="p">(</span><span class="bp">None</span><span class="p">,</span> <span class="n">to_date</span><span class="p">),</span> <span class="n">self</span><span class="p">.</span><span class="n">__ix_locked_to</span><span class="p">.</span><span class="nf">select</span><span class="p">(</span><span class="n">from_date</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span> <span class="p">)</span> <span class="k">return</span> <span class="ow">not</span> <span class="n">overlapping</span> </code></pre> </div> <p>It narrows results by combining two selectors — “starts before <code>to_date</code>” and “ends after <code>from_date</code>” — which is the standard overlap criterion. In <code>dbzero</code>, <code>index.select(a, b)</code> returns items keyed between <code>a</code> and <code>b</code> (inclusive by default). Combining multiple selectors in <code>db0.find(...)</code> typically intersects (logical AND) the candidate sets, while list composition broadens them (logical OR). For exclusions, use <code>db0.no(...)</code>. <code>find</code> returns a lazily‑evaluated iterable, so simply testing its truthiness is an efficient existence check.</p> <p>So we have a base object with a single public method, <code>is_available</code>, ready for future extensions.</p> <p>Finally, we need a general container - for all our object bookings. What does it look like ?<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight python"><code><span class="nd">@db0.memo</span> <span class="k">class</span> <span class="nc">BookingService</span><span class="p">:</span> <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="n">self</span><span class="p">):</span> <span class="n">self</span><span class="p">.</span><span class="n">__ix_locked_from</span> <span class="o">=</span> <span class="n">db0</span><span class="p">.</span><span class="nf">index</span><span class="p">()</span> <span class="n">self</span><span class="p">.</span><span class="n">__ix_locked_to</span> <span class="o">=</span> <span class="n">db0</span><span class="p">.</span><span class="nf">index</span><span class="p">()</span> <span class="k">def</span> <span class="nf">find_booked</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">from_date</span><span class="p">:</span> <span class="n">Any</span><span class="p">,</span> <span class="n">to_date</span><span class="p">:</span> <span class="n">Any</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Iterable</span><span class="p">[</span><span class="sh">'</span><span class="s">BookableResource</span><span class="sh">'</span><span class="p">]:</span> <span class="k">return</span> <span class="n">db0</span><span class="p">.</span><span class="nf">find</span><span class="p">(</span> <span class="n">self</span><span class="p">.</span><span class="n">__ix_locked_from</span><span class="p">.</span><span class="nf">select</span><span class="p">(</span><span class="bp">None</span><span class="p">,</span> <span class="n">to_date</span><span class="p">),</span> <span class="n">self</span><span class="p">.</span><span class="n">__ix_locked_to</span><span class="p">.</span><span class="nf">select</span><span class="p">(</span><span class="n">from_date</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span> <span class="p">)</span> <span class="k">def</span> <span class="nf">find_available</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">from_date</span><span class="p">:</span> <span class="n">Any</span><span class="p">,</span> <span class="n">to_date</span><span class="p">:</span> <span class="n">Any</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Iterable</span><span class="p">[</span><span class="sh">'</span><span class="s">BookableResource</span><span class="sh">'</span><span class="p">]:</span> <span class="k">return</span> <span class="n">db0</span><span class="p">.</span><span class="nf">find</span><span class="p">(</span><span class="n">BookableResource</span><span class="p">,</span> <span class="n">db0</span><span class="p">.</span><span class="nf">no</span><span class="p">(</span><span class="n">self</span><span class="p">.</span><span class="nf">find_booked</span><span class="p">(</span><span class="n">from_date</span><span class="p">,</span> <span class="n">to_date</span><span class="p">)))</span> <span class="k">def</span> <span class="nf">add_booking</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">event</span><span class="p">:</span> <span class="sh">'</span><span class="s">BookingEvent</span><span class="sh">'</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="bp">None</span><span class="p">:</span> <span class="k">assert</span> <span class="ow">not</span> <span class="n">event</span><span class="p">.</span><span class="n">owns_lock</span><span class="p">,</span> <span class="sh">"</span><span class="s">Booking already added to calendar</span><span class="sh">"</span> <span class="k">assert</span> <span class="n">event</span><span class="p">.</span><span class="nb">object</span><span class="p">.</span><span class="nf">is_available</span><span class="p">(</span><span class="n">event</span><span class="p">.</span><span class="n">from_date</span><span class="p">,</span> <span class="n">event</span><span class="p">.</span><span class="n">to_date</span><span class="p">)</span> <span class="c1"># Add to calendar indexes </span> <span class="n">self</span><span class="p">.</span><span class="n">__ix_locked_from</span><span class="p">.</span><span class="nf">add</span><span class="p">(</span><span class="n">event</span><span class="p">.</span><span class="n">from_date</span><span class="p">,</span> <span class="n">event</span><span class="p">.</span><span class="nb">object</span><span class="p">)</span> <span class="n">self</span><span class="p">.</span><span class="n">__ix_locked_to</span><span class="p">.</span><span class="nf">add</span><span class="p">(</span><span class="n">event</span><span class="p">.</span><span class="n">to_date</span><span class="p">,</span> <span class="n">event</span><span class="p">.</span><span class="nb">object</span><span class="p">)</span> <span class="c1"># Lock the object itself </span> <span class="n">event</span><span class="p">.</span><span class="nb">object</span><span class="p">.</span><span class="nf">_add_lock</span><span class="p">(</span><span class="n">event</span><span class="p">)</span> <span class="n">event</span><span class="p">.</span><span class="n">owns_lock</span> <span class="o">=</span> <span class="bp">True</span> <span class="k">def</span> <span class="nf">remove_booking</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">event</span><span class="p">:</span> <span class="sh">'</span><span class="s">BookingEvent</span><span class="sh">'</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="bp">None</span><span class="p">:</span> <span class="k">assert</span> <span class="n">event</span><span class="p">.</span><span class="n">owns_lock</span><span class="p">,</span> <span class="sh">"</span><span class="s">Booking not owned by calendar</span><span class="sh">"</span> <span class="c1"># Remove from calendar indexes </span> <span class="n">self</span><span class="p">.</span><span class="n">__ix_locked_from</span><span class="p">.</span><span class="nf">remove</span><span class="p">(</span><span class="n">event</span><span class="p">.</span><span class="n">from_date</span><span class="p">,</span> <span class="n">event</span><span class="p">.</span><span class="nb">object</span><span class="p">)</span> <span class="n">self</span><span class="p">.</span><span class="n">__ix_locked_to</span><span class="p">.</span><span class="nf">remove</span><span class="p">(</span><span class="n">event</span><span class="p">.</span><span class="n">to_date</span><span class="p">,</span> <span class="n">event</span><span class="p">.</span><span class="nb">object</span><span class="p">)</span> <span class="c1"># Unlock the object itself </span> <span class="n">event</span><span class="p">.</span><span class="nb">object</span><span class="p">.</span><span class="nf">_remove_lock</span><span class="p">(</span><span class="n">event</span><span class="p">)</span> <span class="n">event</span><span class="p">.</span><span class="n">owns_lock</span> <span class="o">=</span> <span class="bp">False</span> </code></pre> </div> <p>It might look complex, but it mirrors the per‑object pattern at the calendar level. The interesting function is <code>find_available</code>:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight python"><code><span class="k">def</span> <span class="nf">find_available</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">from_date</span><span class="p">,</span> <span class="n">to_date</span><span class="p">):</span> <span class="k">return</span> <span class="n">db0</span><span class="p">.</span><span class="nf">find</span><span class="p">(</span><span class="n">BookableResource</span><span class="p">,</span> <span class="n">db0</span><span class="p">.</span><span class="nf">no</span><span class="p">(</span><span class="n">self</span><span class="p">.</span><span class="nf">find_booked</span><span class="p">(</span><span class="n">from_date</span><span class="p">,</span> <span class="n">to_date</span><span class="p">)))</span> </code></pre> </div> <p>It returns an iterable of all <code>BookableResource</code> instances available during the specified dates: “find all <code>BookableResource</code> AND NOT booked in the range.” This kind of composable query is a core <code>dbzero</code> mechanism. Note: it returns a lazy iterable that you can further compose or filter.</p> <p>And that’s it — our foundational data model is ready.</p> <h3> Does it meet all of the technical requirements? </h3> <p>It meets the logical criteria, but what about the technical ones? Let’s revisit:</p> <ul> <li><p><strong>Type‑agnostic</strong> (pass): We deliberately avoided pinning <code>from_date</code>/<code>to_date</code> types; concrete implementations choose day/hour/ms precision.</p></li> <li><p><strong>Composability</strong> (pass): Cleanly composable with other modules (e.g., comments, ratings) without entangling foreign keys across subtypes.</p></li> <li><p><strong>Truly polymorphic</strong> (pass): As long as concrete types derive from <code>BookableResource</code>, you can treat them uniformly or specialize as needed.</p></li> <li><p><strong>Performant</strong> and <strong>scalable</strong> (pass): Private per‑object indexes make the model future‑proof. Start on a single server; scale with read replicas; partition across clusters for global workloads.</p></li> </ul> <h2> Why are foundation models so important? </h2> <p>I can give you a couple of reasons:</p> <ul> <li>AI agents benefit — clearer primitives simplify reasoning and planning.</li> <li>Don’t reinvent the wheel for every booking app when base requirements hold.</li> <li>Foundational models can be well‑tested and maintained, reducing bugs.</li> <li>Performance properties can be analyzed independently of specific domains.</li> <li>Treat it as a first‑class citizen in your project — almost like extending your data language with a few lines of code.</li> <li>Adapt to many booking domains by deriving concrete types.</li> </ul> <p>In short: this is a path to truly composable applications. Build the model once; plug it into many domain‑specific solutions.</p> <p>Stay tuned. In Part 2, I’ll cover concrete integrations and show how this foundation allowed LLMs to build a full‑featured booking service with real availability queries, without N+1 traps.</p> ai python performance api Your Tech Stack Is Limiting Your Creativity Wojciech Kozłowski Sat, 20 Dec 2025 09:19:16 +0000 https://dev.to/dbzero/your-tech-stack-is-limiting-your-creativity-p2l https://dev.to/dbzero/your-tech-stack-is-limiting-your-creativity-p2l <p><a href="proxy.php?url=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%2Fx9cci5w1wuxlzvuge4l6.png" class="article-body-image-wrapper"><img src="proxy.php?url=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%2Fx9cci5w1wuxlzvuge4l6.png" alt=" " width="800" height="436"></a></p> <p>We’ve all been there.<br> It’s a Saturday morning. The sun is shining, the coffee is hot, and you wake up with a jolt of inspiration: The Billion-Dollar Idea.<br> You open your laptop with that fresh weekend energy. By 10:00 AM, you’re flying. You’ve defined your core Python classes, mapped out the data flow, and sketched the logic. With your favorite AI coding assistant riding shotgun, you’ve even spun up a basic frontend. The first artifacts of your creation are alive.<br> What could possibly go wrong?</p> <h2> The 2:00 PM Wall: The Persistence Problem </h2> <p>The complexity starts to creep in. You need a place to keep your users’ data. At first glance, a document database looks promising — flexible, modern, easy. But then you realize it may not scale the way you need. Or maybe you need real transactions. So you switch to Postgres.<br> “Just use Postgres,” they say.<br> Great. Now you realize your hierarchical, deeply nested data doesn’t really fit the relational model all that well. Fine — let’s do this properly. Sound technical modeling. ERD diagrams. Strong types. Your software will be as solid as a medieval fortress.<br> But it takes time.<br> And before you notice, it’s already 5:00 PM.</p> <h2> The Midnight Spiral: The ORM Trap </h2> <p>Ha — but we’re only halfway through.<br> Now we need to connect the database model with our Python classes. Piece of cake, right? Just let SQLAlchemy do the magic.<br> It finally works… after another two hours of sweating over Claude.<br> But oh dear — you forgot to add a critical feature to your app.<br> So you revisit everything:</p> <ul> <li>the data model</li> <li>the ERD</li> <li>indexes</li> <li>SQLAlchemy mappings</li> <li>objects</li> <li>API contracts</li> </ul> <p>It works again.<br> Gosh — it’s well past midnight now.<br> And then it hits you: this is still just a tiny prototype. Any real user load will require caching (Redis? Something custom?). What about data consistency? Race conditions? And of course, you’ll need to process events.<br> Kafka? Maybe microservices?<br> But how will it scale? Do you really know how to shard the data? Or is it enough to just upgrade your $150/month Postgres instance on AWS to $300/month?<br> Overwhelmed by questions with expensive answers, you close the laptop. "I'll look at it tomorrow," you say. But you won't. The spark is gone. The idea is buried under infrastructure.</p> <h2> When Infrastructure Kills Momentum </h2> <p>This is an imagined story — but does it sound familiar?<br> We often start with great ideas, only to watch them get buried under nuances, edge cases, and the drudgery of real-world constraints. AI agents help — for a while. They give us confidence and speed early on, but notoriously give up at the worst possible moment, leaving us alone with critical bugs, mounting technical debt, and architectural mistakes that are expensive to undo.<br> This story highlights a deeper problem: our foundation technologies have become overwhelmingly complex and creatively limiting. It feels almost impossible to start a real project today without a PhD in computer science — or at least ten years of corporate battle scars.</p> <h2> Enter dbzero: Radical Simplification of the Stack </h2> <p>We’ve felt this pain ourselves — many times — and decided to do something about it. That’s how <a href="proxy.php?url=https://dbzero.io" rel="noopener noreferrer">dbzero</a> was born.<br> Dbzero is an <a href="proxy.php?url=https://github.com/dbzero-software/dbzero" rel="noopener noreferrer">open-source</a> Python package you can install right away:</p> <p><code>pip install dbzero</code></p> <p>It promises radical simplification. We believe it can replace large parts of your current stack — including, in many cases, the database itself.<br> The idea behind dbzero is simple — and it’s more about forgetting than learning new things.<br> Just forget about the database.<br> From today onward, let’s agree: no such thing exists.<br> A database is just software sitting on top of your filesystem, doing something useful — but at a high cost. It limits creativity, hurts performance, and floods developers with an endless stream of very serious-sounding terms:<br> atomicity, consistency, isolation levels, row-level locks…</p> <h2> The “Infinite Memory” Philosophy </h2> <p>For most application logic, let’s be honest — these details rarely matter.<br> How often do you think about electrons flowing through CPU circuits? Or photons traveling through fiber-optic cables between your servers?<br> As Harry Percival and Bob Gregory once put it:</p> <blockquote> <p>“If we had infinite memory in our laptops, we’d have no need for clumsy databases. We could just use our objects however we liked.”</p> </blockquote> <p>At dbzero, we believe this idea still holds.<br> Of course, infinite memory alone isn’t enough. We still need important guarantees: atomicity, isolation, transactions, concurrent process safety. And yes — we need to run across not just one laptop, but whole clusters of containers.<br> But here’s the difference:<br> We don’t make these concepts first-class citizens.<br> They are implementation details. Sometimes they matter — but most of the time, for most developers, they don’t. Dbzero lets you use your Python objects however you like, without constantly bending your design around storage constraints.</p> <h2> Build First. Optimize Later. </h2> <p>Dbzero goes beyond objects.<br> We extended the language with tagging. We added memory partitioning (dbzero prefixes). We built powerful querying capabilities — and more.<br> But all of this can come later.<br> These tools are there when you need them — not before. You can start building what feels natural. What makes sense. What will make users fall in love with your software.<br> Forget the data-juggling acrobatics. Forget the persistence boilerplate. Forget the architectural gymnastics you’re forced to perform before you’ve even validated your idea.<br> That problem is no longer yours.<br> It’s ours.</p> <p>So maybe it’s time to open that drawer of unfinished projects and give one of them another chance — this time on dbzero, a simpler yet stronger foundation.</p> webdev database python performance