回到2021年,一个客户找到我,提出了看起来很直接的需求:"我们需要一个拍卖网站。像eBay一样,但是小众的——古董摩托车配件。"三个月、两个被放弃的原型和一次令人尴尬的生产故障后,我有了自己的看法。很强烈的看法。最后我们成功了,但现在我不会用同样的方式构建它。一点都不会。
关键要点:2026年的拍卖平台使用Next.js、带实时通道的Supabase用于实时竞价和Stripe;难点不在技术栈,而在并发环境下的竞价状态完整性。A 2026 auction platform is Next.js, Supabase with realtime channels for live bidding, and Stripe; the hard part is bid-state integrity under concurrency, not the stack.
拍卖平台出人意料地复杂。表面看起来只是商品列表、竞价和计时器。但当两个用户在毫秒内竞价,或你的WebSocket连接在倒计时归零时断开,或你的支付处理器在捕获中途超时——突然你就得向一个非常愤怒的卖家解释为什么他们的1967年BSA Lightning以£12的价格成交了。所以让我逐个工具、逐个决策地走你一遍我在2026年会实际构建什么。
---
核心架构决策:单体还是服务?
不要让任何人为第一版本向你兜售微服务。我是认真的。
我反复看到这个错误——创始人雇一个顾问,顾问在白板上画出八个独立的服务,大家都点头,六个月后什么都没发布,因为团队在调试一个40个用户平台上的跨服务延迟。对于拍卖MVP或甚至中等规模的产品(比如说,每月活跃用户少于50,000),模块化单体是正确的选择。modular monolith is the right call.
我会选择的:Next.js处理前端和API层,搭配Node.js后端。不是因为它很流行。是因为Next.js 14+中的服务器组件模型真正降低了SEO很重要的拍卖商品列表页面的复杂性——你希望这些商品描述被索引。API路由处理轻量级工作;繁重的实时工作在别处(稍后再说)。Next.js on the frontend and API layer, with a Node.js backend. Not because it's trendy. Because the server components model in Next.js 14+ genuinely reduces the complexity of auction listing pages where SEO actually matters -- you want those lot descriptions indexed. The API routes handle lighter lifting; the heavy real-time stuff lives elsewhere (more on that in a moment).
数据库?PostgreSQL。任何事务性的东西都永远用PostgreSQL。拍卖是深度关系型的——用户、商品、竞价、保留价、发票——你希望外键约束做真正的工作,而不是基于直觉的应用逻辑。我会在2026年在Supabase上运行它,因为你得到Postgres、行级安全和真实的实时订阅层内置,这把曾经三个独立的基础设施关注点折叠成一笔账单。Supabase in 2026 because you get Postgres, row-level security, and a real-time subscription layer baked in, which collapses what used to be three separate infrastructure concerns into one bill.
---
实时竞拍:会让你崩溃的部分
这是大多数拍卖平台失败的地方。或至少是跛行的地方。
根本问题:竞价必须感觉是即时的,必须保持一致,必须正确处理竞态条件。如果两个用户在同一毫秒提交竞价,其中一个赢。数据库决定谁赢。不是前端,不是负载均衡器——数据库,通过一个正确编写的带SELECT FOR UPDATE的事务。SELECT FOR UPDATE.
对于实时层本身,我在2026年会使用Ably而不是自己搭建原始WebSocket。我在2022年Seahawk的一个房产拍卖项目上试过原始方法——自托管socket.io、Redis pub/sub,应有尽有。一切顺利,直到出问题了。Ably为你提供有保证的消息排序、连接状态恢复(所以如果竞价者的手机在拍卖中途从WiFi切换到4G,他们不会无声地错过成交竞价),和一个明智的仪表板。大规模的定价是真实的,但对大多数拍卖运营商来说,与基础设施复杂性相比这是九牛一毛。Ably in 2026 rather than rolling raw WebSockets. I tried the raw approach on a property auction project at Seahawk back in 2022 -- self-hosted socket.io, Redis pub/sub, the works. It was fine until it wasn't. Ably gives you guaranteed message ordering, connection state recovery (so if a bidder's phone switches from WiFi to 4G mid-auction, they don't silently miss the winning bid), and a sensible dashboard. The pricing at scale is real, but for most auction operators it's noise compared to infrastructure complexity.
处理"秒杀"问题
拍卖狙击——在最后几秒钟出价——取决于你的客户端,可能是功能也可能是漏洞。eBay 就是著名的允许这种做法。许多专业拍卖行在最后一分钟内收到出价时会将计时器延长 30-60 秒。这被称为"软关闭"或"反狙击"逻辑。从第一天就建立这个机制。规则很简单:
- 竞价在剩余少于 N 秒时到达
- 交易确认竞价有效且为最高出价
- 拍卖结束时间延长 N 秒
- 新的结束时间通过 Ably 广播给所有连接的客户端
这大概是 40 行服务器逻辑。跳过它并在后期拼凑上去会很麻烦。
---
支付:别想太复杂
我见过人们为拍卖网站设置复杂的支付方案,因为拍卖有特殊要求——你提前获取支付细节,只在拍品成交时才收费,可能需要持有定金,如果被超价可能需要立即退款。这些都是真的。这些都可以通过 Stripe 解决,无需离开 Stripe 文档。
2026年Stripe仍然是绝大多数拍卖运营者的正确选择。具体来说: in 2026 is still the right answer for the vast majority of auction operators. Specifically:
- 用于标准出价到收费流程的Stripe Payment Intents for the standard bid-to-charge flow
capture_method: manual来授权卡而不收费(对于保证金冻结至关重要)to authorise a card without charging it (essential for deposit holds)- 如果你正在构建一个多个卖家收到付款的市场,可以使用 Stripe Connect
我要指出的一点是:除非你有法律建议说必须这样做,否则不要在一开始就授权卡片支付全部拍品价值。只授权定金(拍卖界通常是 10-25%),然后在拍品成交后才扣款或取消。你的卡片拒绝率会因此下降。
对于更高价值的拍卖行——经典汽车、美术品之类的——你需要支持银行转账。Stripe 现在通过其支付链接和发票产品可以合理地处理这个问题,但你仍然需要人工参与对账。为此建立一个简单的后台队列;不要自动化那些不需要自动化的东西。
---
搜索和筛选:用 Typesense,不是 Elasticsearch
说实话,拍卖平台上的搜索问题被低估了。用户需要按类别、当前价格、剩余时间、状况、地点进行筛选。而且要快。
Elasticsearch对大多数拍卖网站来说过度设计,而且是真正的运维噩梦。我会用Typesense。它是开源的,你可以在6美元的DigitalOcean droplet上自托管或使用Typesense Cloud,搜索质量对于目录风格的数据来说很出色。通过简单的变更数据捕获钩子或每30秒的cron任务将你的PostgreSQL拍品表同步到Typesense(拍卖拍品价格的实时同步很好但对于搜索来说很少必要)。Typesense is what I'd use. It's open source, you can self-host on a $6 DigitalOcean droplet or use Typesense Cloud, and the search quality is excellent for catalogue-style data. Sync your PostgreSQL lots table to Typesense via a simple change-data-capture hook or a cron job every 30 seconds (real-time sync of auction lot prices is nice but rarely necessary for search).
Typesense 有一个开箱即用处理不好的地方:仅限自提物品的地理搜索。它确实有地理筛选功能,但如果你的拍卖网站有大量"仅限本地取货"的库存,早期花半天时间配置这个。我没有,在 2023 年的一个园艺机械拍卖网站上,后来我们事后改造时花了两倍的功夫。
---
基础设施和托管
这是我 2026 年的默认配置:
- Vercel 用于 Next.js 前端和 API 路由——零配置部署、每个分支的预览 URL、必要时使用边缘函数 for the Next.js frontend and API routes -- zero config deployments, preview URLs per branch, edge functions where needed
- 用于 PostgreSQL 和身份验证的 Supabase for PostgreSQL and auth
- 用于 WebSocket 的 Ably for WebSockets
- 用于搜索的 Typesense Cloud for search
- Cloudflare 在一切之前——免费层可以处理 DDoS、图像优化和缓存,无需复杂配置 in front of everything -- free tier handles DDoS, image optimisation, and caching without fuss
- Uploadcare 或 Cloudinary 用于卖家上传的拍品图片(2026 年请别再把用户上传存在自己服务器上了) or Cloudinary for seller-uploaded lot images (never store user uploads on your own server in 2026, please)
这个技术栈没有 Kubernetes、没有自管理的 Redis 集群、没有 DevOps 招聘。独立开发者或小团队可以运行它。更重要的是——它可以在不重新架构的情况下扩展。当你被行业出版物报道、8000 人在一小时内访问你的网站时,Vercel 和 Supabase 会处理这个流量激增。Vercel and Supabase will handle the traffic spike when you get featured in a trade publication and 8,000 people hit your site in an hour.
一个我经常看到的基础设施错误
人们容易忘记后台任务。拍卖成交事件不是用户触发的——它们在特定时间戳在服务器端发生。你需要一个可靠的任务调度器。我在 2026 年会使用 Inngest。它处理基于时间的触发、重试,并给你一个真正有用的事件日志,当你调试"为什么拍品 447 在没有发送获胜者邮件的情况下关闭"时会派上用场。不要在你的服务器上使用简单的 cron。当你的服务器重启时,你的 cron 状态就消失了。Inngest for this in 2026. It handles time-based triggers, retries, and gives you an event log that's actually useful when you're debugging "why did lot 447 close without sending the winner email". Don't use a simple cron on your server. When your server restarts, your cron state is gone.
---
管理员和卖家工具
卖家需要创建列表、上传图片、设置底价和查看出价历史。买家需要关注列表、出价提醒和发票下载。这些不是光彩的功能。但这些是客户在周四晚上9点打电话给你时会投诉的功能。
对于管理面板,根据预算我会在 Retool 或自定义 Next.js 仪表盘上轻装构建。Retool 真的可以快速搭建,可以处理拍卖管理任务的 80%——批准列表、管理用户、取消出价——而无需编写太多代码。对于任何面向客户的内容,我会在 Next.js 中正确构建,因为 Retool 嵌入在 iframe 中不是一个好的用户体验。Retool or a custom Next.js dashboard depending on budget. Retool is genuinely fast to stand up and handles the 80% of auction admin tasks -- approving listings, managing users, voiding bids -- without writing much code. For anything client-facing I'd build properly in Next.js, because Retool embedded in an iframe is not a good user experience.
电子邮件通知——被超价警报、拍品即将结束、发票已准备——在 2026 年通过 Resend 发送。大约 18 个月前它在我的技术栈中取代了 SendGrid,我再也没有回头看过。开发者体验明显更好,投递能力一直很稳定。Resend in 2026. It replaced SendGrid in my stack about 18 months ago and I haven't looked back. The developer experience is notably better and the deliverability has been solid.
---
拍卖特定的安全考虑
拍卖平台会吸引出价操纵尝试。刷单(卖家用虚假账户抬高自己拍品价格)、账户接管来进行欺诈性赢价出价,以及支付欺诈都是真实存在的,相比典型的电商来说不成比例地常见。
有几件事我会从一开始就设计进去:
- 竞价提交的速率限制 -- 每个用户每分钟每件拍品的最大竞价数量,在 API 层强制执行。Upstash Redis 很适合这个需求;它有一个专门构建的速率限制库。 -- max N bids per user per minute per lot, enforced at the API layer. Upstash Redis is good for this; it has a purpose-built rate limiting library.
- 竞价前需要邮箱验证 -- 听起来显而易见,但能阻止数量惊人的滥用行为 -- sounds obvious, stops a surprising amount of abuse
- 通过 Stripe Radar 进行欺诈评分 -- 已经包含在 Stripe 中了,直接使用就好 -- already included in Stripe, just use it
- 用 IP 和设备指纹识别可疑账户集群 -- 如果你的运营规模有意义,FingerprintJS Pro 的成本是值得的 -- FingerprintJS Pro is worth the cost if you're operating at any meaningful scale
老实说,最重要的是日志记录。记录每一次竞价尝试、每一笔失败的支付、每一个账户操作。当出问题时 -- 迟早会出问题 -- 你需要完整的审计跟踪。Supabase 的内置日志加上 Axiom 的轻量级设置就能搞定,不费什么力气。Axiom covers this without much effort.
---
常见问题
小型本地拍卖网站的最小可行堆栈是什么?
如果你在为一个当地拍卖行构建系统,也许只有 200 个用户和每周一次的销售,你不需要 Ably 或 Typesense。使用 WordPress 配合像 Auctions for WooCommerce 这样的插件,能走得出乎意料地远。我为三家地区拍卖行建过这样的系统 -- 古董、农业设备,那类东西。一旦你需要在高负载下实现真正的实时竞争性竞价,就会快速超出它的能力。WordPress with a plugin like Auctions for WooCommerce gets you surprisingly far. I've set up three of these for regional auction houses -- antiques, farm equipment, that sort of thing. The moment you need real-time competitive bidding under load, outgrow it fast.
我可以用Firebase代替Supabase吗?
可以。Firebase 的 Firestore 实际上对实时竞价状态是一个合理的选择。我在 2026 年更倾向 Supabase 的原因是 SQL -- 拍卖数据有大量的关系结构(拍品属于销售,竞价属于拍品和用户,发票引用竞价),用文档数据库查询这些会变得很混乱。但如果你的团队已经对 Firebase 很了解,别为了换而换。
我应该如何处理拍卖结束时间的时区问题?
所有时间数据都存储在UTC。永远都是。通过浏览器用用户的本地时区显示。这听起来很明显,但我还是在大约五分之一的项目中看到做错了。现代浏览器中的Intl.DateTimeFormat API可以处理显示部分,不需要任何库。Intl.DateTimeFormat API in modern browsers handles the display side without any library.
我需要一个移动应用吗?
对 MVP 来说不需要。一个构建良好的渐进式网页应用配合推送通知(通过 Web Push API)能覆盖竞价者在移动设备上实际需要的 90% 功能。原生应用可以稍后再做,如果业务需要的话。等到那一天,我会用 Expo 和 React Native -- iOS 和 Android 共享代码库,而且团队已经了解 React。Expo and React Native when that day arrives -- shared codebase across iOS and Android, and the team already knows React.
---
在线运营拍卖是一个合理的工程挑战,只是被一个看似简单的 UI 掩盖了。竞价界面就是三个按钮和一个数字。下面的一切 -- 一致性、公平性、实时状态、欺诈防范 -- 才是真正的工作所在。从一开始就把技术栈做对了,剩下的就只是功能而已。做错了,你就是那个要向卖家解释为什么他们的拍品以 £12 成交的人。
构建无趣的基础设施。在其之上构建有趣的产品。
