2021 के एक गुरुवार दोपहर को एक क्लाइंट ने मुझे कॉल किया — Bath में एक एंटीक्स डीलर, जो अपनी मासिक आमने-सामने नीलाम को ऑनलाइन ले जाना चाहता था। काफी आसान लगा, मैंने सोचा। फिर उसने कहा "और बोलियों को सभी के लिए लाइव अपडेट होना चाहिए, बिना पेज रीफ्रेश के।" ठीक है। तब एक "साधारण WordPress काम" दो हफ्ते की आर्किटेक्चर बातचीत में बदल गया।
मैंने Seahawk Media में 5,000 से अधिक साइटें बनाई हैं, और रीयल-टाइम फीचर्स वह हैं जो आपको काटते हैं अगर आप शुरुआत से ही उन्हें सही तरीके से नियोजित न करें। हर पाँच सेकंड में पोलिंग ठीक लगता है जब तक कि 200 बिडर एक ही एंडपॉइंट पर एक साथ न पड़ने लगें और आपका होस्टिंग बिल रात भर दोगुना न हो जाए। तो चलिए मैं आपको दिखाता हूँ कि मैं आज के समय में एक सही लाइव नीलाम प्लेटफॉर्म कैसे बनाऊँ — Next.js और Supabase का उपयोग करके — जो मैंने वास्तव में शिप किया है।Seahawk Media, and real-time features are the ones that bite you if you don't plan them properly from the start. Polling every five seconds sounds fine until you have 200 bidders hammering a single endpoint simultaneously and your hosting bill doubles overnight. So let me show you exactly how I'd build a proper live auction platform today — usingNext.jsandSupabase— based on what I've actually shipped.
---
इसके लिए विशेष रूप से Next.js और Supabase क्यों
सुनिए, रीयल-टाइम करने के दर्जन तरीके हैं। एक Node सर्वर पर Socket.io, Ably, Pusher, Firebase — मैंने सभी का विभिन्न बिंदुओं पर इस्तेमाल किया है। लेकिन Next.js + Supabase संयोजन यहाँ अपनी जगह विशिष्ट कारण के लिए अर्जित करता है: Supabase Realtime PostgreSQL के तार्किक प्रतिकृति के शीर्ष पर निर्मित है, जिसका अर्थ है कि आपके लाइव बिड अपडेट और आपकी स्थायी डेटा लेयर एक ही सिस्टम हैं। दो सत्य स्रोतों को सिंक करने की कोई आवश्यकता नहीं। यह न सोचना कि कोई बिड जो WebSocket में गई वह डेटाबेस में भी पहुँच गई या नहीं।same system. No syncing two sources of truth. No wondering if a bid that went into the WebSocket also made it into the database.
Supabase आपको Auth, Row Level Security, और Storage सभी बॉक्स में मिलते हैं। एक नीलामी साइट के लिए, जहां "केवल नीलामी मालिक ही लॉट समाप्त कर सकता है" और "एक यूजर अपनी खुद की वस्तु पर बोली नहीं लगा सकता" असली बिज़नेस नियम हैं, Postgres में RLS policies बिल्कुल सही टूल हैं।
और Next.js इसलिए कि — ईमानदारी से — App Router with Server Components का मतलब है कि आप नीलामी कैटलॉग को स्टैटिकली रेंडर कर सकते हैं, SEO को खुश रख सकते हैं, और सिर्फ रियल-टाइम बिडिंग विजेट को क्लाइंट पर हाइड्रेट कर सकते हैं। यह विभाजन मायने रखता है। आप किसी पेज पर डायनामिक रेंडरिंग के लिए पैसे खर्च नहीं करना चाहते जो 90% स्टैटिक कंटेंट है।
---
पहले स्कीमा डिज़ाइन करना (इसे स्किप न करें)
यह वह जगह है जहां ज्यादातर लोग जल्दबाजी करते हैं और बाद में इसका पछतावा करते हैं। मैंने Bath एंटीक क्लाइंट के स्कीमा को प्रोजेक्ट के बीच रीफैक्टर करने में शर्मनाक तीन दिन बिताए क्योंकि मैंने bid history मॉडल के बारे में सही तरीके से नहीं सोचा था।
यहाँ मूल संरचना है जो मैं अब उपयोग करता हूं:
- `profiles` — Supabase के auth.users को विस्तारित करता है, display name, verified bidder flag, और credit_balance (अगर आप डिपोजिट-आधारित बिडिंग कर रहे हैं) स्टोर करता है— extends Supabase's
auth.users, stores display name, verified bidder flag, and acredit_balanceif you're doing deposit-based bidding - `auctions` — घटना स्वयं; starts_at, ends_at, status (draft | live | closed), और created_by— the event itself;
starts_at,ends_at,status(draft | live | closed), andcreated_by - `lots` — एक नीलामी के भीतर अलग-अलग वस्तुएं; reserve_price, current_bid, current_bidder_id, lot_number, ends_at (लॉट के अलग-अलग काउंटडाउन हो सकते हैं)— individual items within an auction;
reserve_price,current_bid,current_bidder_id,lot_number,ends_at(lots can have individual countdowns) - `bids` — अपरिवर्तनीय append-only लॉग; lot_id, bidder_id, amount, placed_at। इस टेबल को कभी भी अपडेट न करें। कभी नहीं।— immutable append-only log;
lot_id,bidder_id,amount,placed_at. Never update this table. Ever. - `auction_participants` — एक जॉइन टेबल जो ट्रैक करता है कि किसने किस नीलामी के लिए रजिस्टर किया है (डिपॉजिट होल्ड और नोटिफिकेशन टार्गेटिंग के लिए उपयोगी)— a join table tracking who has registered for which auction (useful for deposit holds and notification targeting)
lots टेबल पर current_bid और current_bidder_id कॉलम जानबूझकर denormalised हैं। हाँ, आप उन्हें हर बार read पर bids टेबल से derive कर सकते हैं, लेकिन concurrent load के तहत वह क्वेरी तेजी से महंगी हो जाती है। इसे denormalise करें, bids टेबल को अपना audit log रखें, और एक Postgres फंक्शन का उपयोग करें ताकि जब कोई bid स्वीकार हो तो lots को atomically अपडेट किया जा सके।current_bidandcurrent_bidder_idcolumns onlotsare denormalised intentionally. Yes, you could derive them from thebidstable on every read, but under concurrent load that query gets expensive fast. Denormalise it, keep thebidstable as your audit log, and use a Postgres function to updatelotsatomically when a bid is accepted.
The Atomic Bid Function
यह वह हिस्सा है जिसे ज्यादातर ट्यूटोरियल स्किप करते हैं। नीलामी में race conditions असली होती हैं। दोनों यूजर एक ही मिलीसेकंड में £520 सबमिट करते हैं — क्या होता है?real. Two users submitting £520 at the same millisecond — what happens?
इसका जवाब है lot row पर FOR UPDATE लॉकिंग के साथ एक Postgres फंक्शन:FOR UPDATElocking on the lot row:
``` create or replace function place_bid(p_lot_id uuid, p_bidder_id uuid, p_amount numeric) returns json as $$ declare v_lot lots%rowtype; begin select * into v_lot from lots where id = p_lot_id for update;
if v_lot.status != 'live' then return json_build_object('success', false, 'error', 'Lot is not live'); end if;
if p_amount <= v_lot.current_bid then return json_build_object('success', false, 'error', 'Bid too low'); end if;
if p_bidder_id = v_lot.current_bidder_id then return json_build_object('success', false, 'error', 'You are already the highest bidder'); end if;
insert into bids (lot_id, bidder_id, amount) values (p_lot_id, p_bidder_id, p_amount);
update lots set current_bid = p_amount, current_bidder_id = p_bidder_id where id = p_lot_id;
return json_build_object('success', true, 'new_bid', p_amount); end; $$ language plpgsql security definer; ```
इसे अपने Next.js API route से supabase.rpc('place_bid', {...}) के माध्यम से कॉल करें। FOR UPDATE lock का मतलब है कि किसी दिए गए समय में प्रति lot केवल एक ट्रांज़ैक्शन जीतता है। दूसरा एक serialisation error पाता है और आप क्लाइंट पर एक friendly "किसी ने आपको outbid कर दिया है" संदेश return करते हैं।supabase.rpc('place_bid', {...}). TheFOR UPDATElock means only one transaction wins per lot at any given moment. The other one gets a serialisation error and you return a friendly "someone just outbid you" message on the client.
---
Row Level Security — नीलामी के नियम की परत
RLS उन चीजों में से एक है जो developers या तो तुरंत पसंद करते हैं या टालते हैं क्योंकि यह अपारदर्शी लगता है। मैं टालने वाले पक्ष में था जब तक कि Seahawk पर एक fintech प्रोजेक्ट ने मुझे सिखाया कि केवल application code में access control को enforce करना एक गलत तरीके से configured API route दूर है।
एक नीलामी साइट के लिए, ये नीतियां मायने रखती हैं:
- कोई भी live lots पढ़ सकता है — SELECT on lots where auctions.status = 'live'—
SELECTonlotswhereauctions.status = 'live' - केवल authenticated, verified bidders ही bids insert कर सकते हैं — policy में profiles.verified_bidder = true check करें— check
profiles.verified_bidder = truein the policy - केवल auction creator ही lot status update कर सकता है — UPDATE on lots where auctions.created_by = auth.uid()—
UPDATEonlotswhereauctions.created_by = auth.uid() - बिड हिस्ट्री लॉट के नीलामकर्ता और बिडर स्वयं द्वारा पढ़ी जा सकती है — किसी और को रीयल-टाइम में पूरी बिड हिस्ट्री देखने की जरूरत नहीं है— no one else needs to see full bid history in real time
Supabase RLS डॉक्यूमेंटेशन यहाँ सच में बहुत अच्छा है — security definer functions के सेक्शन को पढ़ने लायक है, क्योंकि यह place_bid जैसी RPC कॉल्स के साथ इंटरैक्ट करता है।Supabase RLS documentationis genuinely good here — worth reading the section on security definer functions, because it interacts with how RPC calls likeplace_bidwork.
एक गोचा: अगर आप अपने Postgres फंक्शन पर security definer का इस्तेमाल करते हैं (ऊपर की तरह), तो यह फंक्शन ऑनर की प्रिविलेजेस के साथ चलता है, RLS को बाईपास करते हुए। यह इरादतन है — आप चाहते हैं कि बिड प्लेसमेंट बिडर के RLS को बाईपास करे ताकि वह लॉट रो को लॉक और अपडेट कर सके। लेकिन इसका मतलब है कि आपको अपने फंक्शन के अंदर अपना खुद का बिजनेस लॉजिक चेक लागू करना चाहिए, जो ऊपर दिया गया कोड करता है।security defineron your Postgres function (as above), it runs with the function owner's privileges, bypassing RLS. That's intentional — youwantthe bid placement to bypass the bidder's RLS so it can lock and update the lot row. But it means you must enforce your own business logic checks inside the function, which the code above does.
---
Supabase Realtime को Next.js में सेटअप करना
यहीं यह वास्तव में संतोषजनक हो जाता है। Supabase Realtime आपको Postgres टेबल पर चेंजेस को WebSockets का इस्तेमाल करते हुए सबस्क्राइब करने देता है, और क्लाइंट SDK इसे लगभग शर्मनाक रूप से सरल बना देता है।WebSockets underneath, and the client SDK makes it almost embarrassingly simple.
आपके नीलाम लॉट पेज में — Next.js App Router में एक Client Component — आप ऐसा कुछ करेंगे:
``` 'use client'
import { useEffect, useState } from 'react' import { createClientComponentClient } from '@supabase/auth-helpers-nextjs'
export default function LotBidDisplay({ lotId, initialBid }) { const [currentBid, setCurrentBid] = useState(initialBid) const supabase = createClientComponentClient()
useEffect(() => { const channel = supabase .channel(lot-${lotId}) .on( 'postgres_changes', { event: 'UPDATE', schema: 'public', table: 'lots', filter: id=eq.${lotId} }, (payload) => { setCurrentBid(payload.new.current_bid) } ) .subscribe() }, [lotId])lot-${lotId}).on( 'postgres_changes', { event: 'UPDATE', schema: 'public', table: 'lots', filter:id=eq.${lotId}}, (payload) => { setCurrentBid(payload.new.current_bid) } ).subscribe()
return () => { supabase.removeChannel(channel) }
return <div>Current bid: £{currentBid.toLocaleString()}</div> } ```
Server Component से initialBid पास करें जो request के समय ताज़ा डेटा fetch करता है। फिर client संभाल लेता है, उस specific lot row पर UPDATE events को सुनते हुए। हर बार जब place_bid सफल चलता है, Supabase change को broadcast करता है और हर connected bidder का UI लगभग 100–300ms में update हो जाता है।initialBidfrom a Server Component that fetches fresh data at request time. The client then takes over, listening forUPDATEevents on that specific lot row. Every timeplace_bidruns successfully, Supabase broadcasts the change and every connected bidder's UI updates within about 100–300ms typically.
Countdown Timer को Handle करना
Lots के पास आमतौर पर countdown होता है — "closes in 3:42"। इसके लिए client clock पर भरोसा न करें। lots.ends_at (Postgres में UTC में स्टोर किया गया) से end time निकालें और client पर Date.now() का उपयोग करके बचे हुए seconds को calculate करें। हर 60 सेकंड में एक fresh fetch से re-sync करें drift के मामले में। और "soft close" logic जोड़ें: अगर कोई bid आखिरी 60 सेकंड में आती है, तो ends_at को दो मिनट बढ़ाएँ। यह standard auction behaviour है और bidders को यह expect होता है।nottrust the client clock for this. Derive the end time fromlots.ends_at(stored in UTC in Postgres) and calculate remaining seconds on the client usingDate.now(). Re-sync it every 60 seconds with a fresh fetch in case of drift. And add "soft close" logic: if a bid arrives within the last 60 seconds, extendends_atby two minutes. That's standard auction behaviour and bidders expect it.
---
Auction UI के लिए Next.js App Router Architecture
जो page structure मैं use करूँगा:
`` app/ auctions/ page.tsx ← Server Component, live auctions list करता है (ISR, revalidate: 60) [auctionId]/ page.tsx ← Server Component, server-side lots list को fetch करता है LotGrid.tsx ← Client Component, lot status changes को subscribe करता है [lotId]/ page.tsx ← Server Component, initial lot data + SEO के लिए metadata BidPanel.tsx ← Client Component, real-time bid display + bid form ``app/ auctions/ page.tsx ← Server Component, lists live auctions (ISR, revalidate: 60) [auctionId]/ page.tsx ← Server Component, fetches lots list server-side LotGrid.tsx ← Client Component, subscribes to lot status changes [lotId]/ page.tsx ← Server Component, initial lot data + metadata for SEO BidPanel.tsx ← Client Component, real-time bid display + bid form``
कैटलॉग (/auctions) 60-सेकंड के रीवेलिडेशन के साथ Incremental Static Regeneration का उपयोग करता है। अलग-अलग lot पेजेस पहली लोड पर सर्वर-साइड रेंडर होते हैं (शेयरिंग, प्रीव्यूइंग, og:image जेनरेशन के लिए), फिर लाइव stuff के लिए क्लाइंट कंपोनेंट्स को हैंड ऑफ करते हैं।/auctions) uses Incremental Static Regeneration with a 60-second revalidation. Individual lot pages render server-side on first load (for sharing, previewing, og:image generation), then hand off to client components for the live stuff.
एक चीज़ जो मैं हमेशा करता हूँ: BidPanel कंपोनेंट को dynamic(() => import('./BidPanel'), { ssr: false }) के पीछे lazy-loaded रखना। यह वैसे भी क्लाइंट-साइड ही समझ में आता है, और यह slow connections पर यूजर्स के लिए आपके initial HTML payload को lean रखता है — जो, अगर आपके auction audience की उम्र ज्यादा है (जैसे antique auctions में होता है), तो आप जितना सोचते हो उससे कहीं ज्यादा मायने रखता है।BidPanelcomponent lazy-loaded behinddynamic(() => import('./BidPanel'), { ssr: false }). It only makes sense client-side anyway, and it keeps your initial HTML payload lean for users on slow connections — which, if your auction audience skews older (as antique auctions tend to), matters more than you'd expect.
---
Authentication और "Verified Bidder" Flow
Standard Supabase Auth जिसमें email/password या magic link साइन-अप के लिए ठीक काम करता है। लेकिन auctions को अक्सर एक extra step की जरूरत होती है: bidder verification। आपको क्रेडिट कार्ड hold, ID verification, या बस admin approval की जरूरत हो सकती है कोई कोई भी बोली लगाने से पहले।
जो pattern मैं उपयोग करता हूँ: profiles table पर एक verified_bidder boolean, जिसका default false है। साइन-अप के बाद, यूजर को "Complete your registration" स्क्रीन दिखता है। एक बार approved हो जाने पर (manually admin द्वारा, या automatically Stripe payment authorisation के बाद), आप flag को flip करते हैं। bids पर RLS policy इसे check करती है। वे browse कर सकते हैं, देख सकते हैं, लेकिन verified न होने तक बोली नहीं लगा सकते।verified_bidderboolean on theprofilestable, defaulting tofalse. After sign-up, the user sees a "Complete your registration" screen. Once approved (manually by admin, or automatically after a Stripe payment authorisation), you flip the flag. The RLS policy on bids checks it. They can browse, watch, but not bid until verified.
Stripe payment authorisation holds के लिए, Stripe का payment intents जिसमें capture_method: manual है वह सही approach है — आप £50 का hold authorise करते हैं, अगर वे जीतते हैं तो capture करते हैं, अगर नहीं तो release करते हैं। यह no-pay situations को dramatically कम करता है जो, मुझ पर विश्वास करो, हर online auction operator के लिए एक nightmare हैं।Stripe's payment intents with capture_method: manualis the right approach — you authorise a £50 hold, capture it if they win, release it if they don't. This dramatically reduces no-pay situations which, trust me, are the bane of every online auction operator's existence.
---
Deployment, Performance और जो Bits आपको काटेंगे
Vercel पर deploy करो — यह Next.js के लिए obvious choice है और edge network Supabase के global infrastructure के साथ अच्छी तरह काम करता है। सुनिश्चित करो कि तुम्हारा Supabase project AWS region में है जो तुम्हारे Vercel deployment region के सबसे करीब है। मैंने 40–60ms की completely unnecessary latency देखी है क्योंकि किसी ने Vercel को us-east-1 में deploy किया था और Supabase को eu-west-2 में। एक region चुनो, दोनों को वहाँ रखो।Vercel— it's the obvious choice for Next.js and the edge network plays well with Supabase's global infrastructure. Make sure your Supabase project is in the AWS region closest to your Vercel deployment region. I've seen 40–60ms of completely unnecessary latency because someone deployed Vercel inus-east-1and Supabase ineu-west-2. Pick one region, put both there.
कुछ चीजें हैं जो आपको दर्द देंगी अगर आप उन्हें शुरुआत से ही संभाल न लें:
- WebSocket कनेक्शन की सीमाएँ। Supabase का फ्री टियर करीब 200 concurrent Realtime कनेक्शन allow करता है। अगर आपनी नीलामी viral हो जाए, तो यह सीमा मायने रखती है। अपनी plan को check करें।Supabase's free tier allows around 200 concurrent Realtime connections. If your auction goes viral, that cap matters. Check your plan.
- Bids के लिए Optimistic UI। बोली को सर्वर की पुष्टि से पहले बोलीकर्ता की स्क्रीन पर तुरंत दिखाएँ। अगर यह fail हो (outbid, race condition), तो error के साथ revert करें। 200–300ms सर्वर round-trip अगोचर है जब तक UI इसका इंतज़ार न करे।Show the bid immediately on the bidder's screen before the server confirms. If it fails (outbid, race condition), revert with an error. The 200–300ms server round-trip is imperceptibleunlessthe UI waits for it.
- लॉट ending grace period। लॉट को बिल्कुल ends_at पर बंद न करें। in-flight बिड्स को प्रोसेस करने के लिए 2–3 सेकंड की server-side buffer दें जो deadline से पहले सबमिट की गई थीं। इसे अपनी close_lot scheduled function में handle करें।Never close a lot exactly at
ends_at. Give it a 2–3 second server-side buffer to allow in-flight bids that were submitted just before the deadline to process. Handle this in yourclose_lotscheduled function. - ईमेल notifications। Supabase Edge Functions को Resend या Postmark के साथ इस्तेमाल करें "You've been outbid" और "You won!" ईमेल भेजने के लिए। अपने Next.js API routes से यह करने की कोशिश न करें — वे timeout हो सकते हैं, और नीलामी में शामिल लोग genuinely परेशान हो जाते हैं अगर notifications unreliable हों।Use Supabase Edge Functions with Resend or Postmark to send "You've been outbid" and "You won!" emails. Don't try to do this from your Next.js API routes — they can time out, and auction participants get genuinely annoyed if notifications are unreliable.
---
FAQ
Supabase Realtime कितने concurrent bidders को handle कर सकता है?
Supabase की Pro plan default रूप से 500 concurrent Realtime कनेक्शन support करती है, ज़्यादा सीमाएँ उपलब्ध हैं। ज़्यादातर नीलामी साइटों के लिए — जब तक आप Sotheby's के online जैसा कुछ नहीं चला रहे हैं — यह काफ़ी है। अगर आप हज़ारों simultaneous viewers की expect करते हैं, तो lot updates को per-user subscriptions की जगह एक single server-side channel के through broadcast करने पर विचार करें, और Supabase की Realtime Broadcast feature को देखें जो high fan-out scenarios के लिए ज़्यादा efficient है।Realtime Broadcastfeature which is more efficient for high fan-out scenarios.
क्या मुझे Supabase Realtime का इस्तेमाल करना चाहिए या Ably जैसी dedicated service का?
अधिकांश प्रोजेक्ट्स के लिए, Supabase Realtime पूरी तरह पर्याप्त है और इंटीग्रेशन बहुत सरल है क्योंकि आपका डेटा पहले से ही Supabase में है। मैं केवल Ably या Pusher का उपयोग करूंगा अगर आपको ग्लोबली 50ms से कम लेटेंसी चाहिए, या अगर आप लाखों कनकरेंट कनेक्शन के साथ कुछ बना रहे हैं। एक एंटीक्स नीलाम, एक चैरिटी फंडरेज़र, एक छोटी आर्ट गैलरी की ऑनलाइन बिक्री — Supabase इन सभी को ठीक से संभालता है।
अगर यूजर का WebSocket कनेक्शन नीलाम के बीच में ड्रॉप हो जाए तो क्या होता है?
Supabase का क्लाइंट SDK स्वचालित रूप से पुनः कनेक्ट करने का प्रयास करेगा। लेकिन आपको हमेशा पुनः कनेक्शन पर वर्तमान लॉट स्टेट (current_bid, ends_at) को फिर से फेच करना चाहिए, बजाय इसके कि ड्रॉप से पहले लोकल स्टेट में जो कुछ था उस पर भरोसा करें। अपने Client Component में एक online/offline इवेंट लिस्नर जोड़ें और जब कनेक्शन रिस्टोर हो तो एक ताजा सर्वर फेच ट्रिगर करें।current_bid,ends_at) on reconnection rather than trusting whatever was in local state before the drop. Add anonline/offlineevent listener in your Client Component and trigger a fresh server fetch when the connection restores.
क्या मैं एक API रूट की जगह Next.js Server Actions का उपयोग करके बिड प्लेस कर सकता हूं?
हां, और मैंने ऐसा किया है। Next.js 14 में Server Actions सुविधाजनक हैं — वे एक डेडिकेटेड /api/bid रूट के बॉयलरप्लेट को हटाते हैं। ट्रेडऑफ यह है कि Server Actions को व्यक्तिगत रूप से रेट-लिमिट करना थोड़ा मुश्किल है (आप मिडलवेयर लेवल पर रेट लिमिटिंग लागू करेंगे, प्रति-एक्शन के बजाय)। एक प्रोडक्शन नीलाम साइट के लिए, मैं मिडलवेयर में Upstash Redis रेट लिमिटिंग जोड़ूंगा ताकि एक ही यूजर को बिड रिक्वेस्ट स्पैम करने से रोका जा सके, भले ही आप Actions या API रूट्स का उपयोग करें।/api/bidroute. The tradeoff is that Server Actions are a bit harder to rate-limit individually (you'd apply rate limiting at the middleware level rather than per-action). For a production auction site, I'd addUpstash Redisrate limiting in middleware to prevent a single user from spamming bid requests regardless of whether you use Actions or API routes.
मैं टाई को कैसे हैंडल करूं — एक ही समय में दो समान बिड्स?
place_bid Postgres फंक्शन में FOR UPDATE लॉक कनकरेंट बिड्स को सीरियलाइज करता है, इसलिए तकनीकी रूप से डेटाबेस लेवल पर टाई नहीं हो सकता। एक सफल होगी, दूसरी "बिड बहुत कम" रेस्पांस के साथ फेल होगी (क्योंकि दोनों current_bid के बराबर हैं और चेक p_amount <= v_lot.current_bid है)। पहले आओ, पहले जाओ। यह मानक नीलामी अभ्यास है और अधिकांश बोलीदाता इसे समझते हैं।FOR UPDATElock in theplace_bidPostgres function serialises concurrent bids, so technically ties can't happen at the database level. One will succeed, the other will fail with a "bid too low" response (since both are equal tocurrent_bidand the check isp_amount <= v_lot.current_bid). First in, first served. That's standard auction practice and most bidders understand it.
---
Bath के एंटीक्स डीलर ने, जो भी हो, दो साल से भी ज्यादा समय से अपनी मासिक नीलामी ऑनलाइन चला रहे हैं। एक शनिवार की शाम पीक कनकरेंट बिडर्स 84 तक पहुंचे — उनका पूरा गांव जॉर्जियन सिल्वर के एक विवादास्पद लॉट को उसके रिज़र्व से तीन गुना ज्यादा कीमत पर जाते देखने के लिए ट्यून इन कर गया। Supabase को कोई हिलावा नहीं। Next.js को कोई हिलावा नहीं। एकमात्र चीज जो टूटी वह उनका Wi-Fi था, क्योंकि वह इसे शॉप फ्लोर से चला रहे थे।
रियल-टाइम को शुरुआत में सोचना मुश्किल है, लेकिन एक बार स्कीमा ठोस हो जाए और एटॉमिक बिड फंक्शन जगह पर हो, बाकी सब कुछ मोटे तौर पर प्लंबिंग है। फाउंडेशन को सही करो और तुम अपना समय मजेदार चीजों पर बिताओगे — काउंटडाउन एनिमेशन, "गोइंग वंस, गोइंग ट्वाइस" UX — बजाय मध्यरात में रेस कंडीशन्स को डीबग करने के।
