发布于 2026-01-06 2 阅读
0

速度背后看不见的代价:如果今天让我重建我的AI SaaS产品,我会做出哪些改变

速度背后看不见的代价:如果今天让我重建我的AI SaaS产品,我会做出哪些改变

快速开发让你感觉势不可挡。周末冲刺,周五完成原型,周日上线。这就是我开发 Learnflow AI 的全部方法。

表面上看?它奏效了。

用户注册顺利。语音会话进行得很流畅。技术栈(Next.js + Convex + Kinde + Vapi)运行良好。

但几周后,问题开始显现。

用户界面中没有,功能集中也没有。

但本质上。

在我后端代码中预设的假设里,在我为了实现“演示”效果而硬编码的流程里,在我几乎没有为特殊情况、升级、重新认证和回访用户预留空间的地方。

这是我在发布MVP之前最希望看到的一篇文章。

速度并不重要,重要的是你放弃了什么。

起源:周末速成人工智能学习之旅

这个想法很简单:

让任何人都能创建感觉定制化且响应迅速的语音AI导师。

48小时内,我就让它运行起来了:

  • 报名
  • 选择方案(通过 Kinde)
  • 降落在仪表板上
  • 点击“创建导师”
  • 点击“开始会话”

它奏效了。基本奏效了。

我始料未及的事

追求“立竿见影”是有代价的。

以下是逐渐出现的盲点:

1. 入职状态未持久化

我设置了一个引导用户创建第一个导师的步骤说明。它只显示一次。但如果他们刷新页面或稍后回来查看呢?

他们从零开始。

2. 升级逻辑过于脱离实际

Kinde托管了我的价格表,套餐信息也保存到了用户元数据中。但是应用内的逻辑需要手动读取和检查这些信息。我遇到了升级提示出现不及时,甚至根本不出现的问题。

3. 会话跟踪不具备模块化特性

我追踪了会话开始次数并扣除了积分……但并非总是如此。重试流程、连接断开或用户切换设备都会导致一些特殊情况下的问题。

我的解决方法:逐层修复

1. 通过 Convex 进行入职状态跟踪

我没有使用本地状态或仅限前端的逻辑,而是将入职步骤跟踪移到了后端。

export const setOnboardingStep = mutation({
  args: { userId: v.id("users"), step: v.string() },
  handler: async (ctx, args) => {
    await ctx.db.patch(args.userId, { onboardingStep: args.step });
  },
});
Enter fullscreen mode Exit fullscreen mode

现在,无论用户从哪里登录,我都可以:

  • 简历入职
  • 根据他们最后出现的步骤进行分支逻辑
  • 在合适的时机触发升级提示

图表:入职流程前后对比

2. 信用执行作为中间件

前:

  • 我在按钮点击事件处理程序中手动检查了用户积分。
  • 诸如重复呼叫或会话中断等极端情况未涵盖在内。

现在:

  • 我将信用检查封装在一个专门的突变体中
  • 该变异会在任何会话开始之前运行
export const canStartSession = query({
  args: { userId: v.id("users") },
  handler: async (ctx, args) => {
    const user = await ctx.db.get(args.userId);
    const isPro = user?.plan === "pro";
    const hasCredits = user?.credits > 0;
    return isPro || hasCredits;
  },
});
Enter fullscreen mode Exit fullscreen mode

用于前端:

const allowed = await api.sessions.canStartSession({ userId });
if (!allowed) return showUpgradeModal();
Enter fullscreen mode Exit fullscreen mode

图示:信用审核流程

3. 模块化会话跟踪

旧模式:

  • startSession刚刚更新了演职员表
  • 但它没有存储元数据:哪个导师,何时,从哪个设备。

新模式:

export const addSession = mutation({
  args: {
    userId: v.id("users"),
    companionId: v.id("companions"),
    timestamp: v.optional(v.string()),
  },
  handler: async (ctx, args) => {
    await ctx.db.insert("sessions", {
      userId: args.userId,
      companionId: args.companionId,
    });
  },
});
Enter fullscreen mode Exit fullscreen mode

这使我能够:

  • 查看每个用户的历史记录
  • 根据行为触发升级提示
  • 可视化每位导师的使用情况

我采用的更优架构模式

功能标志

if (user.plan === "pro")我现在改用

function hasFeature(user, feature) {
  if (user.plan === "pro") return true;
  return freePlanFeatures.includes(feature);
}
Enter fullscreen mode Exit fullscreen mode

更清洁。更易于维护。集中式管理。

事件钩子

我希望行动反应之间能有更好的分离。

我没有在每次会话启动失败后进行硬编码,而是showUpgradeModal()使用了事件发射器模式:

events.on("session-blocked", () => {
  showUpgradeModal();
});
Enter fullscreen mode Exit fullscreen mode

这意味着我以后可以替换用户界面反应,而无需修改业务逻辑。

可组合逻辑:信用 + 计划

与其将计划逻辑分散在几十个地方,我现在将其整合在一起。

function canUseFeature(user, feature) {
  if (user.plan === "pro") return true;
  if (!user.credits || user.credits <= 0) return false;
  return freePlanFeatures.includes(feature);
}
Enter fullscreen mode Exit fullscreen mode

金德:哪些方法奏效,哪些无效

✅ 哪些方法有效

  • 托管定价页面 = 即时流程
  • 元数据同步(会话中的计划信息)
  • 轻松切换免费版和专业版套餐

⚠️ 需要改进的地方

  • Kindle 元数据不是实时更新的(切换套餐后需要手动同步)。
  • 没有内置的使用强制执行机制
  • 我需要通过凸查询来实现自己的门控。

不过,Kinde已经很好地处理了身份验证层。我只需要构建强制执行层即可。

如果从今天开始,我会做不同的选择

  1. 设计署名权从第一天起就生效。
    • 用户不看文档
    • 如果使用情况不可见,就不会有人升级。
  2. 在后端跟踪新用户注册和会话状态
    • 仅前端状态很脆弱
  3. 使升级逻辑响应式而非静态。
    • 根据用户的操作而非他们所在的页面来触发提示。
  4. 模块化信用检查
    • 永远不要仅仅依赖前端逻辑。
  5. 尽早规划基于角色的用户界面
    • 通过分级计划来控制使用频率有助于防止过度使用。

最后想说的话

MVP的速度很棒。

但每一次速度提升都会带来一些弊端,而这些弊端最终都需要你来解决。

那不是失败,创业公司就是这样运作的。

如果你和我几周前一样:

  • 快速启动
  • 努力保持苗条身材
  • 不确定定价逻辑应该深入到什么程度。

记住:

快速发货,但也要为未来的自己留出空间。

使信用系统、升级提示和会话强制执行可组合

使新用户引导状态持久化

并确保二次用户无需从零开始。

有疑问或想发布自己的 AI MVP 吗?

欢迎留言或私信我。我正在公开开发 Learnflow AI,它由Kinde、Convex、Vapi 以及类似这样的课程提供支持。

文章来源:https://dev.to/sholajgede/the-unseen-cost-of-speed-what-id-change-if-i-rebuilt-my-ai-saas-today-455m