跳到主要内容

用半年时间,断断续续做了一个出海 Side Project

· 阅读需 8 分钟
Gwynn
独立开发者 · wawov 作者

最近半年,我一直在断断续续地做一个自己的 Side Project。

说是“做产品”,其实一开始并没有给自己设定多么宏大的目标。我只是想完整地尝试一次出海:从一个想法开始,把产品做出来,让海外用户能够访问、注册、使用,最后通过 Stripe 完成付款。

以前也做过不少项目,但大多数时候,我负责的只是整个系统中的一部分。真正从零开始,把产品、支付和基础设施整套流程亲手串起来,还是第一次。

为什么要做这个项目

做 Side Project 的念头其实一直都有,只是过去常常停留在“做一个功能”这一步。

功能完成了,页面也能打开,看起来像是一个产品,但距离真正上线还有很长一段路:

  • 用户如何注册和登录?
  • 免费用户和付费用户有什么区别?
  • 订阅套餐如何设计?
  • 支付成功之后,系统如何准确发放权益?
  • 用户取消订阅、续费失败或者申请退款时,数据如何处理?
  • 服务出现异常时,如何定位问题?
  • 产品部署之后,如何低成本地持续运行?

这些问题单独看都不算新鲜,但只有真正把它们组合到一起,才会发现“实现一个功能”和“交付一个产品”完全是两回事。

所以这次做 Side Project,我给自己的目标并不是快速做出一个 Demo,而是尽量按照一个真实线上产品的标准,把完整链路走一遍。

即使最后产品没有获得大量用户,这些过程本身也会变成下一次开发的基础。

打通 Stripe 支付,比接一个 API 复杂得多

Stripe 的开发体验很好,文档和测试环境也比较完善。第一次跑通 Checkout,看到测试支付成功时,会觉得支付接入似乎没有那么复杂。

但 Checkout 成功,只是整个支付系统的开始。

一个真正可以上线运行的订阅产品,还需要处理不少细节:

  • 创建客户和订阅关系
  • 区分不同的价格与套餐
  • 接收并验证 Webhook
  • 保证支付事件可以重复执行而不产生脏数据
  • 根据账单状态发放或回收用户权益
  • 处理续费成功、续费失败、取消订阅和退款
  • 让本地订单、用户状态与 Stripe 保持一致
  • 为异常情况保留日志和人工修复能力

这里最容易出现的问题,是把浏览器跳转到“支付成功页面”当成付款成功的最终依据。

实际上,前端页面可能被关闭,网络可能中断,同一个 Webhook 也可能被重复发送。真正可靠的做法,是以 Stripe 服务端事件为准,在自己的系统中建立清晰的订单和权益状态,并保证每个事件都可以被安全地重复处理。

把这些流程做完之后,我才真正理解:支付不是一个按钮,也不是一次 API 调用,而是一套需要长期保持一致的状态系统。

这套代码的价值也不只属于当前项目。用户、套餐、订单、订阅、账单、权益、Webhook 幂等和异常补偿,这些能力在大多数 SaaS 产品中都可以复用。

相比某一个具体功能,这可能才是这个 Side Project 最重要的产出。

这次更在意“生产级代码”

Side Project 很容易陷入两个极端。

一个极端是过度设计,产品还没有用户,就先搭建一套复杂到难以维护的架构;另一个极端是只追求尽快上线,所有逻辑都写在一起,只要当前流程能够运行就算完成。

这次我的选择是:不过度预测未来,但把已经确定的核心链路认真做好。

例如支付事件需要幂等,关键状态需要落库,外部服务调用需要明确错误边界,不同环境的配置需要隔离,数据库变更需要能够迁移,线上问题需要留下足够的信息用于排查。

这些工作在开发时并不会带来特别明显的视觉变化,却决定了产品能不能放心地交给真实用户使用。

我也开始有意识地把项目中的通用能力拆出来。下一次再做新产品时,登录、支付、订阅、权益、部署和监控不需要全部从头开始,而是可以在一套经过实际运行验证的代码上继续迭代。

对独立开发者来说,真正能够提高效率的并不是“这一次写得有多快”,而是每完成一个项目,手里都能多一块可靠的积木。

Cloudflare 对独立开发者真的很友好

这个项目的基础设施几乎全部放在 Cloudflare 上。

不得不说,Cloudflare 对于有想法、想快速把产品做出来的独立开发者,确实非常友好。

从域名、DNS、CDN,到应用运行、数据存储和静态资源服务,很多能力都可以在同一个平台上完成。各个产品之间的接入也比较自然,不需要为了上线一个早期产品,先维护一堆服务器和复杂的网络配置。

我很喜欢 Cloudflare 的一点,是它让基础设施更接近代码。

项目的配置、环境变量、数据库绑定和部署流程都可以跟随代码一起管理。开发完成之后,通过一套相对简单的流程就能发布到全球网络,而不需要先购买服务器、配置 Nginx、申请证书,再单独处理扩容和安全问题。

对于 Side Project 来说,这一点非常重要。

早期产品最稀缺的资源通常不是机器,而是开发者自己的时间和注意力。少维护一台服务器,少处理一次证书续期,少折腾一套部署环境,就能把更多精力放回产品本身。

Cloudflare 的免费额度和按使用量计费方式,也让项目在用户量还很小的时候几乎没有基础设施压力。产品可以先上线、先验证,再随着真实使用逐步增加投入。

这种体验很适合独立开发:想法出现后,可以用很低的成本开始;产品有用户后,也不需要立刻迁移整套架构。

当然,Serverless 并不意味着完全没有复杂度。运行时限制、数据库访问方式、异步任务和不同环境之间的差异,仍然需要认真设计。但总体来看,Cloudflare 帮我省掉了大量与产品核心价值无关的运维工作。

它不只是“便宜”,更重要的是足够顺滑。

出海,先从真正上线开始

以前提到“出海”,很容易先想到市场选择、增长渠道、本地化和商业模式。

这些当然都很重要,但对于一个仍处在开发阶段的 Side Project 来说,第一步其实很朴素:让一个海外用户可以顺利打开网站、理解产品、注册账号、完成付款,并获得他购买的服务。

只有这条链路真正跑通,后面的增长和运营才有意义。

在这个过程中,还会遇到很多国内产品开发中不一定优先考虑的问题,比如英文文案、时区、货币、税务提示、邮件送达、隐私政策以及不同地区用户的访问体验。

出海并不是把中文页面翻译成英文,也不是接入 Stripe 之后就自然拥有了海外市场。它更像是重新学习一次如何完整地交付产品。

这个过程很慢,也有很多琐碎的工作,但当整条链路终于可以稳定运行时,获得的成就感和完成一个普通功能很不一样。

半年之后,我得到了什么

这个项目做得并不连续。

有时候一周能推进很多,有时候因为其他事情停上十几天。重新打开代码时,也经常需要先回忆之前做到哪里,再继续解决下一个问题。

但这种断断续续的节奏,反而更接近独立开发的真实状态。没有专门的团队,也没有严格的项目排期,只能在有限的时间里不断做取舍。

半年之后,产品本身当然还远没有到“成功”的程度,但我已经得到了几样很确定的东西:

  • 完整走通了一次从产品开发到上线收费的流程
  • 对 Stripe 订阅和支付状态有了更深入的理解
  • 建立了一套可以继续复用的生产级代码
  • 实际体验了以 Cloudflare 为核心的 Serverless 基础设施
  • 对独立产品真正需要处理的问题有了更具体的认识

这些积累很难通过只看文档或者只做 Demo 获得。

很多问题必须等到产品真的准备收钱、真的准备交给用户使用时,才会暴露出来。也只有亲手解决过一次,下一次面对相似问题时,才能更快地做出判断。

写在最后

我现在越来越觉得,Side Project 的意义不一定是立刻做出一个成功的产品。

它也可以是一块属于自己的试验田。

可以在里面验证想法,尝试新的技术栈,补齐过去没有完整经历过的产品环节,也可以把一次次踩坑沉淀成下一次能够直接使用的代码和经验。

这半年虽然推进得断断续续,但至少已经从“我也想试试做一个出海产品”,走到了“我完整做过一次,并且它真的可以收款和提供服务”。

这中间的距离,比想象中要长。

不过一旦走完第一次,下一次就不会再从零开始了。