从零开始建立一个初创企业: 我作为CTO所犯的错误
当我第一次被邀请帮助建立一个新的创业公司的技术方面时,我还没有了解到我正在进入什么。我被一个朋友邀请去审核前任技术负责人和开发人员开始的解决方案。然而,由于不可预见的情况,他们两人都决定离开这个项目。我只剩下一个刚刚开始的产品,没有团队继续工作。
当我第一次被邀请帮助建立一个新的创业公司的技术方面时,我还没有了解到我正在进入什么。我被一个朋友邀请去审核前任技术负责人和开发人员开始的解决方案。然而,由于不可预见的情况,他们两人都决定离开这个项目。我只剩下一个刚刚开始的产品,没有团队继续工作。
这家初创公司正在开发一个应用程序,以帮助用户找到最好的交易和业务,以充分利用他们的时间和金钱。该应用应该将用户与那些在非高峰期有多余库存或产能的公司联系起来,使他们能够利用折扣和交易。要求是为iOS和Android建立一个移动应用,以及为企业主建立一个网络管理门户,以管理他们的产品并与客户沟通。此外,所有的购买都必须通过我们的应用程序。
由于没有团队,而且期限很紧,我知道我必须快速行动。我首先组建了一个工程师团队,建立后台、管理门户网站和移动应用程序。虽然我们对我们想要实现的目标有一个清晰的愿景,并有一个坚实的计划,但我知道,这个愿景和计划在未来会有多次改变。寻找合适的工程师所花的时间比我预期的要多,相应地调整我们的策略也很关键,但我还是建立了一个伟大的团队,能够执行我们的愿景并适应不断变化的环境。
利用微服务构建可扩展的后端: 我们的经验
当我开始为我们的创业公司建立后台时,我知道可扩展性和适应性将是关键。经过广泛的搜索,我找到了一个在Node.js方面有经验的高度熟练的后端开发人员。我们一起决定使用微服务架构来构建我们的后端。我们做出这个决定是基于我们初创公司需求的动态性质,以及在找到移动和网络开发人员之前我们有额外的时间。
我有一些基础设施方面的经验,所以我承担了建立云、Kubernetes集群、监控和日志以及编码基础设施的任务。我们使用GitLab进行版本控制,并使用CI/CD管道来自动化构建、测试和部署过程。我们选择JSON-RPC作为通信协议,Node.js作为后端。我们的后端开发人员选择了MongoDB作为数据库,而我更喜欢Postgres。
我们最终有几个微服务,包括:
- Products: 这个微服务包含管理合作伙伴提供的产品和交易、他们的零售地点和促销活动的信息。通过它,人们可以创建、更新和调节它们。它还处理活动的启动和停止。
- Biz Users: 这个微服务管理公司和他们的员工以及管理面板上的Auth服务中的数据。
- Orders: 它负责处理购物车和订单的生命周期,以及与支付系统整合。
- Gate:该微服务位于客户端到后台的两个入口处(从移动设备和从管理面板)。它在客户端和后端之间保持一个websocket连接,将请求引向认证服务或门面。
- Admin Facade和User Facade是后台的facade微服务。它们将客户端的请求分配给服务。它封装了系统的内部结构,并只授予对客户端可用的方法的访问。
- Auth:这个微服务负责接受用户认证和授权。
- File:该服务负责管理静态资源(如产品照片或与合作伙伴的法律文件),它与Yandex整合,用于数据存储。
- App Users: 这个微服务负责管理移动应用程序的用户。在其他方面,它存储了用户的元信息:最后一次看到的,朋友,等等。
- Settings: 这个微服务负责管理应用程序的设置。
- Marketing: 这个微服务负责管理营销活动和促销活动,以及建议。
- 电子邮件、推送和短信通知服务负责与各自的供应商整合。
该平台有几个外部集成:与供应商CloudPayments的支付,与推送、短信和电子邮件服务的通知,以及与Yandex云对象存储使用静态文件(如图片)。
我们花了2–3个月的时间来寻找移动和网络开发人员,但那时,我们已经有了坚实的后台基础设施。在开发过程中,我们能够多次改变概念和要求,而微服务架构使我们很容易对后端进行相应的调整。
我们的移动开发人员非常出色,几次重新制作移动应用程序,以配合我们的首席执行官和设计团队的每一个新设想。客户端应用程序和后端之间的通信是通过使用json rpc协议的websocket进行的。我们在前端使用Vue.js,在移动端使用React Native,这有助于团队的一致性和代码共享。
总的来说,我们到处使用JavaScript是非常好的,因为这有助于工程师们相互阅读代码,并进行必要的修改,以更新服务的通信方式,特别是在移动应用和网络应用。
Supabase简介
当我们推出我们的创业公司时,我们在博客上发表了关于我们在建立科技公司时所面临的挑战。我们从社区收到了很多反馈,其中有些是负面的,但也有很多是建设性的。其中一个让我印象深刻的反馈是,有人建议使用Firebase这样的服务来简化我们的后台。
当时,我不认为使用Firebase是一个好主意,因为它感觉像是一个巨大的供应商锁,我担心会失去对我们的数据和基础设施的控制。
剧透一下:几个月后,我们的创业公司未能获得牵引力,我们不得不关闭它。正是在这段时间里,我在浏览最新的Y Combinator批次时发现了Supabase。Supabase感觉是我在开始创业工作时就应该找到的解决方案。
它是一个开源平台,旨在简化为网络和移动应用构建可扩展和安全的后端过程。它建立在Postgres之上,为管理数据库、认证、实时数据同步和存储对象提供了一套工具和服务,同时仍然让你控制你的数据和基础设施。它的一些主要功能包括:
- 自动生成API: Supabase为你的Postgres数据库自动生成REST、GraphQL和实时websocket通知,使你能够快速、轻松地从网络和移动应用程序中访问你的数据。
- 用户认证和授权: Supabase提供了对用户认证和授权的内置支持,使你的应用安全和保护敏感数据变得容易。
- 实时性: Supabase可以使你的网络和移动应用程序与数据库保持同步,消除了手动刷新数据的需要。
- 存储:你可以存储大型对象,如图像或文件,你也可以提出调整图像大小的请求。
- 可扩展性和安全性: Supabase是建立在Postgres之上的,它可以很容易地纵向和横向扩展,并具有加密和RLS等安全功能。
Supabase是初创公司和小团队的绝佳选择,他们希望快速轻松地建立一个后台,而不必担心复杂的设置和自己维护整个Infra。而且,即使在一个大的科技公司,当你推出一个新的服务时,你也应该考虑Supabase或类似的开源项目。
What if Supabase
在本节中,我们将换个角度,想象一下如果我们从一开始就使用Supabase,我们的创业公司会有怎样的变化。与其花几个月的时间来构建微服务,我们本可以专注于真正重要的东西:我们的用户和我们的产品。我将把所有的时间都投入到寻找移动开发者上,而不是Infra,我将能够专注于后端。
Supabase会使设置和管理数据库变得轻而易举,它的内置服务会取代我们大部分的微服务。这将节省我们的时间、金钱和麻烦。而且它不会让我们失去适应变化和需求的能力,这是我们最重要的优势之一。不幸的是,我们当时并不知道Supabase,但也许你知道,它可以改变你的创业公司的故事。
让我们来看看我们本可以用Supabase的不同功能来取代什么。
Auth
首先,Supabase的内置认证和用户管理服务可以取代我们单独的认证和用户管理微服务。这将为我们提供用户注册、登录,以及管理用户角色和权限。此外,Supabase对基于角色的访问控制(RLS)的支持将使我们能够实现对数据的细粒度访问。例如,用户只能查看自己的订单,而企业主可以编辑他们的产品,管理员可以访问所有数据。
Storage
使用Supabase的内置文件存储将简化处理文件上传、下载和管理的过程,消除对额外存储解决方案的需求。Supabase的内置文件存储将使我们能够利用其功能,如产品图片的大小调整,使我们能够即时创建预览,而不是有一个单独的文件微服务。此外,我们可以使用Supabase的文件存储来安全地存储和管理需要我们的业务用户签署的法律文件,为我们提供一个集中的位置来存储和访问所有这些重要的文件,而不需要额外的第三方服务。
// Request a small resized image of a product from Supabase Storage:
await storage.from('mama_jane').download('pizza.jpeg', {
transform: {
width: 200,
height: 200,
format: 'origin',
},
})
Gateways And Facades
有了Supabase,我们就可以告别我们的两个网关和门面微服务,负责处理移动应用和Web应用与其他微服务之间的通信。Supabase的自动PostgREST和GraphQL API会处理这一切,使我们能够专注于其他事情。
# Retrieve a feed with products from app using Supabase generated GraphQL API
{
retailersCollection(
filter: {active: {eq: true}},
) {
edges {
node {
name
productsCollection {
edges {
node {
id
title
imageUrl
price
}
}
}
}
}
}
}
Products
当涉及到我们的产品和设置微服务时,它主要是作为一个数据所有者,为我们的产品处理CRUD操作。但是通过Supabase,我们可以完全跳过这些服务,而直接使用Postgres的力量。这将使我们能够直接在数据库中处理一些更复杂的操作,如需要交易的产品更新。至于作为该服务一部分的内部钩子和cron作业,Supabase对pg_cron、触发器、webhooks和无服务器功能的支持也能起到同样的作用。
推送
我们还可以用无服务器函数和Supabase中的表的触发器来取代我们的推送、短信和邮件微服务。例如,我们可以在订单表上设置一个触发器,在用户的订单得到确认时向其发送推送通知。发送短信和电子邮件的情况也是如此。我们本可以使用触发器在某些事件发生时自动发送消息,例如用户的账户被创建或新产品被添加。这将大大降低我们架构的复杂性,使其更容易适应需求的变化。想象一下,我们的营销经理想要运行一个活动,并向在过去30天内没有下过订单的用户发送推送通知。有了Supabase,这可以通过在订单表上创建一个简单的触发器来轻松实现。
营销活动
顺便说一下,这个例子告诉我们,我们也不再需要营销服务。这是因为我们可以像上面的例子那样,设置由特定行动触发的自动活动。或者通过引入一个名为marketing_campaigns的新表。然后,我们的营销经理可以简单地在表中插入一个新的行,并加上参数,比如要通知哪些用户。该表的触发器将调用一个无服务器函数来发送推送通知。
--Trigger to send push notifications after the
--marketing specialist adds a marketing campaign to the database.
create or replace function insert_marketing_campaign() returns trigger as $$
begin
insert into marketing_campaigns (message, user_group, start_date)
values (new.message, new.user_group, new.start_date);
perform send_push_events();
return null;
end;
$$ language plpgsql;
create trigger insert_and_send_push
after insert on marketing_campaigns
for each row
execute function insert_marketing_campaign();
Admin studio
现在回想起来,我意识到为我们的商业客户建立一个定制的管理门户可能不是最好的决定。尽管我最初持保留意见,但我的伙伴们坚持要开发它。然而,事实证明,我们的客户还没有准备好浏览一个新的和不熟悉的界面。Supabase仪表板会使我们的销售团队很容易管理我们的商业客户的产品。也许我曾说服我的合作伙伴暂缓开发一个单独的、定制的管理门户,直到我们有了更多的用户,并对他们的需求有了更好的了解。
Orders
这样我们就只剩下订单服务了。从技术上讲,我们可以用无服务器函数和触发器来代替它,但我更愿意保持它的原样。主要原因是我更喜欢这样,因为这是一个非常敏感的问题。但是,如果我们使用Stripe作为我们的支付提供商,我们可以利用Supabase的新包装器功能,使用postgres_fdw从Postgres内部直接向Stripe发送查询,这样就可以达成交易了。然而,只要花一点额外的时间和精力,我们就有可能为我们的支付提供商创建自己的包装器,将其与Supabase集成。
// Listen for stripe events using Supabase Edge Functions
// (to keep track of invoice-paid events, for example)
serve(async (request) => {
const signature = request.headers.get("Stripe-Signature");
const body = await request.text();
let receivedEvent;
try {
receivedEvent = await stripe.webhooks.constructEventAsync(
body,
signature!,
Deno.env.get("STRIPE_WEBHOOK_SIGNING_SECRET")!,
undefined,
cryptoProvider
);
} catch (err) {
return new Response(err.message, { status: 400 });
}
console.log(receivedEvent);
return new Response(JSON.stringify({ ok: true }), { status: 200 });
});
一些想法
我们的创业公司也非常依赖地理数据。我们本可以利用PostGIS(Postgres的一个空间数据库扩展器)的力量来处理我们所有的地理数据需求。这将使我们能够轻松地在我们的应用程序中纳入基于位置的搜索和地图等功能。总的来说,利用Supabase及其与PostgresSQL的集成,将大大简化我们的架构,使我们能够专注于开发我们应用程序的核心功能。使用Supabase可以改变我们创业公司的游戏规则。我不认为它能使我们免于倒闭,但它肯定会在开发和基础设施方面为我们节省一些费用。
比较
使用Supabase,我们就不需要生产和暂存的Kubernetes集群,也不需要管理MongoDB实例和监控基础设施(我们使用弹性堆栈)。这将减少我们创业公司的基础设施成本。此外,这将使我能够专注于寻找一个开发人员来开发我们的移动应用程序,而不是需要找到几个工程师来开发微服务和管理门户。这将导致每月节省高达6–7千美元的成本,这些成本可以投资于其他业务领域。总的来说,Supabase为我们的初创公司提供了一个更简单、更经济的选择,值得任何初创公司或大公司内的服务部门考虑。至少,这是我的看法。
而重要的是,我并不害怕被供应商锁定。你可以使用各种编程语言与Supabase一起工作,包括JavaScript、Dart、Python或Go。这使得你可以灵活地构建和维护你的应用程序。此外,Supabase被设计成可扩展的,使其既适合小型创业公司,也适合大型企业。它可以在云中或内部使用,并与其他开源项目集成。这使得在构建和部署你的应用程序时具有高度的定制性和灵活性。
总而言之, 言而总之
总之,正如我们在自己的创业历程中所经历的那样,建立一个微服务架构可能是一项具有挑战性和成本高昂的工作。然而,Supabase提供了一个更简单、更具成本效益的替代方案,其内置功能可以取代一个典型的初创企业所需的许多微服务。从用户管理和文件存储到实时API和自动数据管理,Supabase有可能同时节省时间和金钱。
虽然我无法在我们自己的创业公司中使用Supabase,但我希望我们的经验和见解能够鼓励其他人考虑将其作为自己项目的可行选择。虽然Supabase可能不是每个项目的最佳选择,但它值得作为一种选择来考虑,或者至少在市场上寻找其他可能更适合你的需求的替代品。我会强调Pocketbase是一个可能的选择,但我仍然会在大多数项目中选择Supabase。而只在某些需要大量定制Golang代码的基础设施开发项目中使用Pocketbase。
P.S.:
距离我写这篇文章的第一稿已经有一段时间了,当我回想Supabase可以如何帮助我之前的创业公司时,我不禁渴望成为Supabase团队的一员。想象一下,当我收到他们的电子邮件,宣布他们正在招聘一个QA职位时,我是多么惊讶。我立即提出申请,令我高兴的是,我收到了录用通知。现在,作为Supabase团队的一员,我有机会在几个个人项目中与该平台合作,并亲眼目睹它如何协助其他初创企业和大公司建立他们的产品。能够成为一家在科技行业产生如此重大影响的公司的一员,令人激动。