เมื่อได้ยิน Next.js ความคิดแรกอาจเป็นเว็บไซต์ static หรือ frontend ที่ขับเคลื่อนด้วย React แต่นั่นแค่ส่วนหนึ่งของเรื่อง Next.js ยังสามารถเป็น backend API ที่มีฟีเจอร์ครบครัน ได้ ซึ่งคุณสามารถโฮสต์และขยายสเกลได้เหมือน backend service อื่นๆ
ในบทความก่อนหน้า ผมอธิบายการสร้าง Next.js API และปรับใช้กับ Sevalla ตัวอย่างเก็บข้อมูลใน PostgreSQL และจัดการ request โดยตรง ใช้งานได้ดี แต่วันที่ traffic เยอะขึ้น API ที่ต้อง query database ทุก request จะช้าลง
ที่นี่ caching เข้ามาช่วย ด้วยการเพิ่ม Redis เป็น cache layer เราสามารถทำให้ Next.js API เร็วขึ้นและมีประสิทธิภาพมากขึ้น ในบทความนี้ เราจะดูวิธีเพิ่ม Redis caching ให้ API ปรับใช้กับ Sevalla และแสดงผลการปรับปรุงที่วัดได้
ในบทความล่าสุด ผมอธิบาย API รายละเอียดแล้ว ดังนั้นคุณสามารถใช้ repository นี้เป็นฐานสำหรับโปรเจกต์นี้
สารบัญ
- ทำไม Caching ถึงสำคัญ
- Redis คืออะไร
- ตั้งค่าโปรเจกต์
- จัดเตรียม Redis (Provisioning Redis)
- อัปเดต Cache เมื่ออ่าน (Updating Cache on Reads)
- อัปเดต Cache เมื่อเขียน (Updating Cache on Writes)
- ปรับใช้บน Sevalla (Deploying to Sevalla)
- ทำไม Redis จึงทำงานดีกับ Next.js APIs
- สรุป
ทำไม Caching ถึงสำคัญ
ทุกครั้งที่ API ของคุณ hit database มันใช้เวลาและทรัพยากร Database เก่งที่จัดเก็บและ query structured data แต่ไม่ได้ optimize สำหรับความเร็วในระยะใหญ่เมื่อต้อง serve พันๆ read requests ต่อวินาที
Caching แก้ปัญหานี้โดยเก็บข้อมูลที่เข้าถ่ายบ่อยไว้ในหน่วยความจำ แทนที่จะถาม database ทุกครั้ง API สามารถส่งคืนข้อมูลจาก cache ได้ทันทีหากมี Redis เหมาะสมที่สุดเพราะเป็น in-memory key-value store ที่ออกแบบมาสำหรับประสิทธิภาพ
ตัวอย่าง: หากดึงรายการผู้ใช้จาก database ทุก request อาจใช้ 200ms รัน query และส่งคืนผลลัพธ์ ด้วย Redis caching request แรกเก็บผลลัพธ์ในหน่วยความจำ และ request ต่อๆ ไปส่งคืนข้อมูลเดียวกันในไม่เกิน 10ms นั่นคือการปรับปรุง 20 เท่า
Redis คืออะไร
Redis คือ in-memory data store ทำงานเหมือนฐานข้อมูลที่เร็วมาก แทนที่จะเขียน/อ่านจากดิสก์ มันเก็บข้อมูลในหน่วยความจำ ทำให้มันเร็วมาก นั่นคือเหตุที่มันมักใช้เป็น cache ซึ่งความเร็วสำคัญกว่าการจัดเก็บระยะยาว
มันออกแบบมา handle high-throughput workloads ด้วย latency ต่ำมาก ตอบสนองในไมโครวินาที ทำให้เหมาะสำหรับ use cases เช่น caching API responses, เก็บ session data หรือขับเคลื่อน real-time applications เช่น chat systems และ leaderboards
ต่างจาก traditional database Redis โฟกัสที่ความเรียบง่ายและความเร็ว เก็บข้อมูลเป็น key-value pairs ดึงหรืออัปเดตค่าได้เร็วโดยไม่ต้องเขียน query ซับซ้อน และรองรับ advanced data types เช่น lists, sets, hashes ทำให้ยืดหยุ่นกว่า key-value store ธรรมดา
เมื่อรวมกับ API อย่างที่เราสร้างใน Next.js Redis ช่วยลดโหลดบน database หลัก และส่ง response ที่เร็วเหให้ไคลเอ็นต์
ตั้งค่าโปรเจกต์
Clone repository:
git clone git@github.com:manishmshiva/nextjs-api-pgsql.git next-api
เข้า directory และ npm install:
cd next-api
npm i
สร้าง .env file ใส่ database URL จาก Sevalla ใน environment variable:
cat .env
.env ควรเป็นแบบนี้:
PGSQL_URL=postgres://<username>:<password>-@asia-east1-001.proxy.kinsta.app:30503/<db_name>
ทดสอบว่าแอปพลิเคชันทำงานได้ปกติ โดยรันแอปและส่ง API requests สองสามครั้ง
เริ่มแอป:
npm run dev
ตรวจสอบว่า database เชื่อมต่อแล้ว ไป localhost:3000 บนเบราว์เซอร์ ควรได้ JSON กลับมา:

สร้าง user ใหม่ ผ่าน Postman ส่ง POST request พร้อม JSON:
{"id":"d9553bb7-2c72-4d92-876b-9c3b40a8c62c","name":"Larry","email":"larry@example.com","age":"25"}

ตรวจสอบว่าบันทึกสร้างแล้ว ไป localhost:3000/users บนเบราว์เซอร์

ดีแล้ว ตอนนี้มา cache APIs นี้ด้วย Redis
จัดเตรียม Redis (Provisioning Redis)
ไปที่แดชบอร์ด Sevalla คลิก "Databases" เลือก "Redis" จากรายการ ตัวเลือกอื่นๆ ใช้ค่า default

เมื่อสร้าง database เสร็จ เปิด "external connection" และ copy publicly accessible URL

ใน .env ควรเป็นแบบนี้:
REDIS_URL=redis://default:<password>@<host>:<port>
ติดตั้ง Redis client สำหรับ Node.js:
npm install ioredis
ตอนนี้เราเชื่อมต่อ Redis และใช้เป็น cache layer สำหรับ users API ได้แล้ว มาดูการ implement caching
อัปเดต Cache เมื่ออ่าน (Updating Cache on Reads)
นี่คือ users/route.ts ที่อัปเดตแล้ว ใช้ Redis:
import { NextResponse } from "next/server";
import { Client } from "pg";
import Redis from "ioredis";
const redis = new Redis(process.env.REDIS_URL!);
async function readUsers() {
const client = new Client({ connectionString: process.env.PGSQL_URL });
await client.connect();
try {
const result = await client.query("SELECT id, name, email, age FROM users");
return result.rows;
} finally {
await client.end();
}
}
export async function GET() {
try {
// ตรวจสอบ cache ก่อน
const cached = await redis.get("users");
if (cached) {
return NextResponse.json(JSON.parse(cached));
}
// Fallback ไป database หากไม่มีใน cache
const users = await readUsers();
// เก็บผลลัพธ์ใน cache พร้อม TTL 60 วินาที
await redis.set("users", JSON.stringify(users), "EX", 60);
return NextResponse.json(users);
} catch (err) {
return NextResponse.json({ error: "Failed to fetch users" }, { status: 500 });
}
}
ตอนนี้เมื่อ hit /users:
- API ตรวจสอบ Redis ก่อน
- หากมีข้อมูล ส่งคืนทันที
- หากไม่มี Query PostgreSQL เก็บผลลัพธ์ใน Redis แล้วส่งคืน
ทำให้ request ซ้ำๆ เร็วมาก คุณปรับ cache expiry (EX 60) ได้ตามความสดของข้อมูลที่ต้องการ
โดยไม่มี Redis caching การ fetch /users สิบครั้ง = สิบ database queries แต่ละอันอาจใช้ 150–200ms ขึ้นอยู่กับขนาด database และ network latency
ด้วย Redis request แรกยังใช้ ~200ms เพราะ populate cache แต่ request ต่อจากนั้นเกือบ instant มักต่ำกว่า 10ms นั่นคือการปรับปรุง 20x
ความเร็วนี้สำคัญเมื่อ API ของคุณเผชิญร้อยๆ หรือพันๆ requests ต่อวินาที Caching ไม่แค่ลด latency แต่น้ำหนักโหลดบน database ด้วย
อัปเดต Cache เมื่อเขียน (Updating Cache on Writes)
ตอนนี้แค่ GET requests ใช้ cache แตถ้าเพิ่ม user ใหม่ Cache จะยังส่งคืนข้อมูลเก่า
วิธีแก้คืออัปเดตหรือล้าง cache ทุกครั้งที่มีการเขียน มาอัปเดต POST handler:
export async function POST(req: Request) {
try {
const body = await req.json();
const client = new Client({ connectionString: process.env.PGSQL_URL });
await client.connect();
const query = `
INSERT INTO users (id, name, email, age)
VALUES ($1, $2, $3, $4)
RETURNING *;
`;
const result = await client.query(query, [
body.id,
body.name,
body.email,
body.age,
]);
await client.end();
// Invalidate cache เพื่อให้ GET ถัดไปดึงข้อมูลใหม่
await redis.del("users");
return NextResponse.json(result.rows[0]);
} catch (err) {
return NextResponse.json({ error: "Failed to add user" }, { status: 500 });
}
}
ตอนนี้ทุกครั้งที่สร้าง user ใหม่ cache สำหรับ users จะถูกล้าง GET request ถัดไปจะดึงจาก database refresh cache และต่อไป serve จาก cache ต่อ
ปรับใช้บน Sevalla (Deploying to Sevalla)
Push โค้ดขึ้น GitHub หรือ fork repository ของผม ตอนนี้ไป Sevalla สร้างแอปใหม่

เลือก repository จาก dropdown ติ๊ก "Automatic deployment on commit" จะทำให้ deploy อัตโนมัติทุกครั้งที่ push โค้ด เลือก "Hobby" ภายใต้ resources

กด "Create" ไม่ใช่ "Create and deploy" เรายังไม่ได้เพิ่ม PostgreSQL URL และ Redis URL เป็น environment variables แอปจะ crash ถ้าพยายาม deploy
ไปส่วน "Environment variables" เพิ่ม key "PGSQL_URL" และ URL ใน value ทำซ้ำสำหรับ "REDIS_URL" key และ Redis URL

กลับไปส่วน "Overview" กด "Deploy now"

เมื่อ deploy เสร็จ กด "Visit app" ได้ live URL ของ API แทนที่ localhost:3000 ด้วย URL ใหม่ใน Postman และทดสอบ API
ทำไม Redis จึงทำงานดีกับ Next.js APIs
Redis เบา เร็วมาก และเหมาะสำหรับ caching API responses ในบริบทของ Next.js มันเข้ากันได้ดีเพราะ:
- API routes รันฝั่งเซิร์ฟเวอร์ (server-side) ที่ Redis สามารถ query โดยตรง
- Cache logic ง่ายต่อการเพิ่มรอบ database calls
- Redis ใช้ได้มากกว่า caching – เช่น rate limiting, session storage, pub/sub ก็เป็น pattern ปกติ
ด้วยการรวม Next.js, PostgreSQL, และ Redis บน Sevalla คุณได้ stack ที่เร็ว ขยายสเกลได้ และปรับใช้ง่าย
สรุป
Caching ไม่ใช่แค่ optimization – มันเป็นความจำเป็นสำหรับ real-world APIs Next.js ช่วยสร้าง backend APIs ที่แข็งแกร่งและปรับใช้ง่าย ด้วยการเพิ่ม Redis เข้าไป APIs นั้นจัดการ scale ได้โดยไม่หงุดหงิด
Sevalla รวมทุกอย่างไว้ด้วยกัน โดยให้ managed PostgreSQL, Redis, และ app hosting ในที่เดียว ด้วย environment variables หลายตัวและ GitHub repo คุณไปจาก local dev ถึง production-ready cached API ในไม่กี่นาที
หวังว่าจะชอบบทความนี้ สมัคร newsletter ฟรีของผม TuringTalks.ai สำหรับ tutorials เน้นปฏิบัติการเกี่ยวกับ AI เพิ่มเติม หาผมได้ที่ Linkedin.
Learn to code for free. freeCodeCamp's open source curriculum has helped more than 40,000 people get jobs as developers. Get started