Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Redis

Upstash ขับเคลื่อนการเติบโตเร็วของ PlanTripAI: กลยุทธ์สำคัญและเรื่องราวความสำเร็จ

ในบทความนี้ ผมสำรวจบทบาทสำคัญของ Upstash ในการพัฒนา PlanTripAI สตาร์ทอัพวางแผนการเดินทางขับเคลื่อนด้วย AI การใช้ Upstash Redis มีบทบาทสำคัญในการจัดการด้านสำคัญ เช่น เก็บ license keys สำหรับเข้าถึงผู้ใช้ และบันทึก/แคช trip content อย่างมีประสิทธิภาพ นอกจากนี้ ฟีเจอร์ Rate Limit ของ Upstash เล่นบทบาทสำคัญในการปกป้องระบบ จัดการความถี่ request ให้การป้องกันที่แข็งแกร่งต่อ security threats และรับประกันบริการที่ราบรื่นต่อเนื่องสำหรับผู้ใช้

plantripai.com เป็น AI-based trip planner สร้าง itinerary เฉพาะบุคคลอย่างรวดเร็วจาก preferences: destination, ระยะเวลาพัก, travel style, budget มี unlimited itinerary creation และ download formats หลากหลาย

  • @upstash/redis
  • @upstash/ratelimit
  • next.js

วิธีการทำงาน

บริษัท AI ทั่วไปมักมีหลายวิธีให้ผู้ใช้ลองผลิตภัณฑ์ ที่ PlanTripAI เราให้ทั้ง freemium และ paid plan

ในแผน freemium (ยอดนิยมสุด): ทุกครั้งที่ผู้ใช้สร้าง trip โดยไม่มี valid license จะสร้าง random key ใหม่ เก็บใน Redis hash (redis.hset(trip:${key}, data)) พร้อม trip content Key ให้ temporary access ไปหน้ารายละเอียด trip เมื่อ access หมดอายุ ผู้ใช้ตัดสินใจว่าจะรักษา permanent access ได้หรือไม่

Freemium users มี rate limit (fixedWindow) 3 requests ต่อ 10 วินาที ป้องกัน attacks

Upstash ขับเคลื่อนการเติบโตเร็วของ PlanTripAI: กลยุทธ์สำคัญและเรื่องราวความสำเร็จ

แผน paid: ผู้ใช้ซื้อผ่าน payment gateway webhook emit success event เก็บ key ใน Redis เป็น valid key (redis.set(${licenseKey}, true))

ผู้ใช้ paid สร้าง trip: สร้าง random key เก็บใน Redis เพิ่ม trip ใหม่ใน user object link กับ license key

Paid users ได้ rate limit กว้างขึ้น ตรวจสอบ valid key ใน Redis แบบไดนามิก

Upstash ขับเคลื่อนการเติบโตเร็วของ PlanTripAI: กลยุทธ์สำคัญและเรื่องราวความสำเร็จ

เก็บ Trip Data

PlanTripAI ใช้ Redis เก็บ trips ที่ผู้ใช้สร้าง Redis เหมาะเพราะ key-value store ที่เร็ว Trips ที่สร้างแล้ว immutable และ hashes ให้เก็บ metadata พร้อม key data

โครงสร้าง trip data ใน Redis hash:

{
  "itinerary": [
    { "day": "Day 1", "data": [...] }
  ],
  "info": "This itinerary is designed for a city explorer visiting Paris, France for 2 days.",
  "inputs": {
    "city": "Paris, France",
    "days": 2,
    "accommodation": "Paris France Hotel",
    "kind": "city explorer",
    "currency": "USD",
    "budget": 3000,
    "transportation": "bus"
  },
  "createdAt": ...,
  "shareable": false
}

ใช้ Upstash Redis API over HTTP เก็บใน free Redis database (10,000 requests/วัน ฟรี พอสำหรับความต้องการ)

import { Redis } from "@upstash/redis";
const redis = new Redis({
  url: "..." // UPSTASH_REDIS_REST_URL
  token: "..." // UPSTASH_REDIS_REST_TOKEN
});
redis.hset(`trip:${id}`, data);

เก็บ Valid License Keys

Paid subscription: แต่ละ paid user ได้ valid license key เก็บใน Redis เหมาะสำหรับ quick validation (key-value DB ที่เร็ว)

Mark user ว่า valid:

import { Redis } from "@upstash/redis";
const redis = new Redis({ url: "...", token: "..." });
await redis.set(licenseKey, true);

Verify user validity:

import { Redis } from "@upstash/redis";
const redis = new Redis({ url: "...", token: "..." });
const redisLicenseKey = await redis.get(licenseKey);
const valid = Boolean(redisLicenseKey);
if (!valid) {
  return new Response(
    JSON.stringify({ message: "The license key is invalid!" }),
    { status: 401 }
  );
}
// successful code here...

นำ Rate Limits ไปใช้

ฟีเจอร์สำคัญปกป้องแอป: rate limit logic รองรับโดย Upstash Rate Limit (รายละเอียดเพิ่มเติม) บริการนี้สำคัญสำหรับ seamless experience ทั้ง free และ paid users ป้องกัน attacks จากผู้ใช้ร้ายได้สำเร็จโดยไม่กระทบแอปโดยรวม

Code snippet ใช้ next.js middleware จัดการ IP checks ตัดสินใจ proceed หรือไม่:

import { NextResponse, type NextFetchEvent, type NextRequest } from "next/server";
import { Ratelimit } from "@upstash/ratelimit";
import { Redis } from "@upstash/redis";

const cache = new Map();
const ratelimit = new Ratelimit({
  redis: Redis.fromEnv(),
  limiter: Ratelimit.fixedWindow(3, "10s"),
  ephemeralCache: cache,
  analytics: true,
});

export default async function middleware(
  request: NextRequest,
  event: NextFetchEvent
): Promise {
  const id = request.ip ?? "anonymous";
  const blockeds = [];
  if (blockeds.includes(id.trim())) {
    return new NextResponse(
      JSON.stringify({ message: "Blocked :)" }),
      { status: 429, headers: { "Content-Type": "application/json" } }
    );
  }
  const { success, pending, limit, reset, remaining } = await ratelimit.limit(id);
  event.waitUntil(pending);
  request.headers.set("X-RateLimit-Limit", limit.toString());
  request.headers.set("X-RateLimit-Remaining", remaining.toString());
  request.headers.set("X-RateLimit-Reset", reset.toString());
  return success ? NextResponse.next() : new NextResponse(
    JSON.stringify({ message: "Request cannot be processed! You sent too many requests in a given amount of time." }),
    { status: 429, headers: { "Content-Type": "application/json" } }
  );
}
export const config = {
  matcher: ["/api/generate-trip", "/api/get-license/(.*)"],
};

คำสุดท้าย

ขอบคุณที่อ่าน! PlanTripAI เริ่มต้นเป็น side project จากความอยากรู้เกี่ยวกับการผสาน Upstash Redis กับ Next.js ใน SaaS framework

หวังว่าจะมีประโยชน์และให้ insight คำถามหรือ feedback ยินดีต้อนรับ ติดต่อได้ที่ Twitter