用静态HTML + Supabase + IP地理定位API构建全球计分板,通过避免event日志、使用聚合表和优化查询等技巧实现零成本高可靠性。展示了在免费层约束下的关键优化决策。
我想看看在不运行服务器、不支付托管费用或在流量激增时耗尽免费层数据库的情况下,一个零成本后端堆栈能走多远。
结果是 Tap The World — 一个全球共享的实时计分板,地球上的每个访客都能点击一次,通过 IP 地理定位实时归属到他们的国家。

🔴 试试在线演示:taptheworld.netlify.app
Frontend:单个 index.html 文件(HTML、CSS、原生 JavaScript)
Database:Supabase(免费层 PostgreSQL)
Hosting:Netlify(静态边缘部署)
Geolocation:ipwho.is(免费客户端 IP 查询,支持 CORS)
构建实时公共计数器的默认做法是为每次点击记录一个事件,并使用 WebSocket 推送实时更新。在免费层上,这会在几分钟内摧毁你的数据库。
以下是我围绕这些限制的设计方案:
我没有为每次点击插入一个事件行,而是将 PostgreSQL 表结构设为:
create table country_counts (
country_code text primary key,
country_name text,
count bigint default 0
);
数据库表永远保持在约 200 行以下。无论网站收到 10 次点击还是 10,000 次点击,查询性能和存储都完全保持不变。
为每个并发访客保持持久 WebSocket 连接会快速耗尽 Supabase 免费层的连接限制。
相反,前端每 2 秒轮询一次 SELECT * FROM country_counts。为了实现暗色分离式翻页显示板的美学效果,2 秒的机械滴答感觉很自然,并能保持服务器负载可预测。
由于没有后端服务器,浏览器直接与 Supabase 通信。为了防止任何人打开浏览器控制台并发送 UPDATE country_counts SET count = 999999,我撤销了匿名用户对该表的直接 INSERT 和 UPDATE 权限。
所有点击都通过自定义 PostgreSQL 函数传递:
create or replace function tap(p_country_code text, p_country_name text)
returns bigint
language plpgsql
security definer
as $$
-- Secure upsert logic increments the country count atomically
$$;
公开 API 密钥仅有 tap() 的 EXECUTE 权限,使得从 REST API 无法破坏模式。
我目前正在探索轻量级边缘速率限制,以补充客户端 localStorage 垃圾邮件检查,而不增加后端服务器成本。
我很想听听你对以下方面的反馈:
PostgreSQL 模式和函数设计。
你在纯静态/无服务器设置中如何处理速率限制!
为你的国家点一次,并在评论中告诉我你的想法!👇
如需进一步操作,你可以考虑屏蔽此人和/或举报滥用行为