TL;DR: NirvaDeploy ตั้งราคา 3 bands ตามประเทศ — เวียดนามจ่าย ฿99 สำหรับ Hobby, สวิสจ่าย ฿149 สำหรับเหมือนกัน, ไทย domestic จ่าย ฿111. ตลาดพัฒนาแล้วช่วย subsidize emerging markets. รวมทุก band aggregate revenue ≥ cost. เราเรียกว่า "อโหสิร่วมกัน" (mutual karmic give-and-receive). บทความนี้คือ math + architecture + code ที่ทำให้มันใช้งานได้จริง.
ปัญหาที่พยายามแก้
Scenario 1: นักพัฒนาเวียดนาม
- รายได้เฉลี่ย: ~$300/mo
- Railway Hobby: $5/mo = ~1.7% ของรายได้
- 1.7% ของรายได้ในประเทศที่รายได้ $300 = น่ารัก feels like commitment
- ผลลัพธ์ใช้งานจริง: ส่วนใหญ่ไม่ผ่านขั้น "พิจารณาราคา" → ใช้ free
tier แล้ว self-host ด้วย DigitalOcean droplet $4/mo แทน
Scenario 2: นักพัฒนาสวิส
- รายได้เฉลี่ย: ~$8,500/mo
- Railway Hobby: $5/mo = 0.06% ของรายได้
- 0.06% = effectively free
- ผลลัพธ์: ราคาไม่เป็น barrier, แต่ก็ไม่ feel "premium" → user อาจ
สงสัยว่า service จริงจังไหม
Scenario 3: บริษัทเรา
- ขาย NirvaDeploy Hobby ที่ ฿111 (~$3.17) ทั้งสองตลาดได้ไหม?
- เวียดนาม: ยังแพงไปสำหรับ student
- สวิส: ดูเหมือน side project หรือ scam
- ที่บริษัท: รายรับเฉลี่ยน้อย, ความรู้สึก "fair" ไม่เกิด
ปัญหาคือ flat pricing เป็น regressive — คนรวยจ่ายเหมือนคนจน แต่ผลกระทบทาง psychology + accessibility ต่างกันมาก. SaaS หลายเจ้า แก้โดยใช้ USD เป็น base, แต่ก็ยังไม่ adjust ตามเศรษฐกิจประเทศ.
ทำไมไม่ใช้ pure donation?
ทางเลือกหนึ่งคือ donation model — ใครจ่ายเท่าไรก็ได้ ใครจ่าย $0 ก็ได้. ฟังดูดี — "เรา trust users, ทุกคนได้ใช้".
ปัญหาเชิงข้อมูล:
- Wikipedia: donation conversion ~1.5% ของ user. Wikipedia ใช้
ต้นทุน hosting น้อยมาก (text-based, heavily cached) → ทำได้
- Bandcamp (pay-what-you-want music): conversion 3-5% สำหรับ
albums ที่มี suggested price > $0. Bandcamp ยังขาย physical merchandise + cut 10% จาก paid sales
- Patreon-style PaaS: ยังไม่มีตัวอย่างที่ scale
ของเรา ต้นทุน Phase 1-3 = ฿75/free user/mo (Railway compute pass-through). ที่ 1,000 users:
- Cost: ฿75,000/mo
- Donation revenue @ 2% conversion × ฿250 avg = ฿5,000/mo
- = covers 7% of cost. ขาดทุน 93%.
Pure donation ไม่ viable สำหรับ PaaS ที่มี real compute cost.
วิธีของเรา: Karma Pricing 3-band
แทนที่จะใช้ราคาเดียวทั่วโลก หรือพึ่ง donation, เราตั้ง 3 price bands ตามรายได้ต่อหัวของประเทศ (GNI per capita, World Bank 2024). ราคาเป็น round numbers — อ่านง่าย, จำง่าย, ไม่ต้องอธิบายทศนิยม.
| Band | Hobby | Pro | Business | Subsidy class |
|---|---|---|---|---|
| 🌏 Neighbor | ฿99 | ฿299 | ฿799 | Subsidized |
| 🇹🇭 Baseline | ฿111 | ฿333 | ฿888 | Baseline (Thailand domestic) |
| 💎 Premium | ฿149 | ฿399 | ฿1,199 | Supporter |
ทำไม 3 bands ไม่ใช่ 7? เราเคยมี 7 bands (emerging → premium แบบ ละเอียด). ปัญหาคือ user อ่าน pricing page แล้ว สับสน — "ผมอยู่ mid-developed หรือ mid-emerging?" 3 bands ยังคง cross-subsidy model แต่ legible กว่า: เพื่อนบ้าน / ไทย / โลกพัฒนาแล้ว.
ตัวอย่างการ map ประเทศ:
- Neighbor: VN, ID, PH, KH, LA, MM, BD, PK, IN, NP, LK
- Baseline: TH (home market — Thailand domestic)
- Premium: ทุกประเทศที่เหลือ — US, GB, DE, CH, JP, SG, MY, AU, …
ปัจจัยที่เราใช้ map:
- GNI per capita (primary)
- PPP (Purchasing Power Parity)
- Card-fraud rate per region (Stripe Radar data)
- Local competitor pricing (cross-check vs DigitalOcean / Vultr regional)
Canonical price table อยู่ใน web/lib/karma-pricing.ts — ทุก endpoint, pricing page, และ Stripe checkout อ่านจากที่เดียวกัน.
ปรัชญา: อโหสิร่วมกัน
ในภาษาบาลี "อโหสิ (aho-si)" แปลตรงๆ ว่า "let it be released, let go". "อโหสิกรรม" คือการยกหนี้ทางกรรม — ยกเลิกพันธะที่ติดค้างกันทางใจ.
ในบริบทธุรกิจ เราใช้ "อโหสิร่วมกัน" หมายถึง:
ผู้ที่มีกำลังจ่ายมากกว่า ช่วยจ่ายให้คนที่จ่ายน้อยกว่า, ทุกคนได้ใช้บริการเดียวกัน, ไม่มีใครรู้สึกว่าถูกเอาเปรียบ.
นี่ไม่ใช่ charity (charity = one-way, top-down). มันคือ mutual exchange — ตลาดพัฒนาแล้วได้ feature ครบ, ตลาด emerging ได้ accessibility, บริษัทได้ aggregate margin.
ทำไมไม่แค่ให้ส่วนลด neighbor? เพราะถ้าราคา US Hobby = ฿111, มันดูถูกจน suspicious. ราคา ฿149 (~$4.26) สำหรับ US ดู "fair", และ ส่วนต่าง ฿50 ต่อ user ต่อเดือน (premium vs neighbor) คือ subsidy budget ที่ explicit.
Math — ทำไม "ไม่ขาดทุน"
Marginal cost per user (Phase 1-3, Railway-backed):
| Tier | Compute | Stripe | Overhead | Total |
|---|---|---|---|---|
| Free | ฿65 | — | ฿10 | ฿75 |
| Hobby | ฿175 | ฿16 | ฿10 | ฿201 |
| Pro | ฿700 | ฿31 | ฿16 | ฿747 |
| Business | ฿2,800 | ฿68 | ฿24 | ฿2,892 |
Phase 4+ projection (Hetzner own infra):
| Tier | Total cost/mo |
|---|---|
| Free | ฿18 |
| Hobby | ฿51 |
| Pro | ฿167 |
| Business | ฿572 |
สำคัญ: ทุก band's price > Phase 4 marginal cost — แม้ neighbor Hobby (฿99) ยัง profitable บน infra ของเราเอง (฿99 > ฿51).
1,000-user Hobby mix simulation
ที่ realistic distribution (dominant Thai + SEA, growing Western tail):
| Band | N | Revenue/mo | Phase 1-3 Cost | Phase 4 Margin |
|---|---|---|---|---|
| Neighbor | 350 | ฿34,650 | ฿70,350 | +฿16,800 |
| Baseline | 400 | ฿44,400 | ฿80,400 | +฿24,000 |
| Premium | 250 | ฿37,250 | ฿50,250 | +฿24,500 |
| Total | 1,000 | ฿116,300 | ฿201,000 | +฿65,300 |
Phase 1-3 aggregate coverage = 58% — gap ที่เหลือเป็น planned acquisition spend (land-grab บน Railway). Phase 4 flip เป็น +฿65,300/mo profit ที่ mix เดียวกัน.
Flat-price comparison
ถ้าเราเก็บ ฿111 ทั่วโลก (Thai baseline):
| Metric | Flat ฿111 | Karma 3-band |
|---|---|---|
| Phase 1-3 Hobby revenue | ฿111,000 | ฿116,300 (+5%) |
| Phase 1-3 cost coverage | 55% | 58% |
| Phase 4 profit/mo | ฿60,000 | ฿65,300 (+9%) |
| Emerging accessibility | ✗ ($3.17 USD ยังแพงใน VN) | ✓ ฿99 = $2.83 |
| Premium market read | ✗ ($3.17 ดูถูกน่าสงสัย) | ✓ $4.26 = "standard SaaS" |
Conclusion: Karma แม้ subsidize neighbor แต่รายได้รวม เพิ่ม 5% Phase 1-3 + กำไรเพิ่ม 9% Phase 4 เพราะ developed markets จ่ายราคา ที่ "fair" สำหรับเขา ไม่ใช่ราคาที่ดูถูกน่าสงสัย.
ปัญหา: VPN gaming
โมเดลนี้มี loophole ชัดเจน:
US developer ใช้ VPN ไป VN → เห็นราคา ฿99 (neighbor) → ใช้ US bank card จ่ายราคา neighbor band
ถ้าเรา honor ราคาที่ user เห็น = US user จ่าย ฿99 = เสียมาร์จิ้น ฿50/mo ต่อ VPN-attacker (premium ฿149 − neighbor ฿99).
Defense: max(geoBand, billingBand)
ที่ checkout, เรามี 2 signals:
- geoCountry =
X-Vercel-IP-CountryหรือCF-IPCountry
(จาก CDN edge — บอกว่า user มาจาก IP ของ network ไหน)
- billingCountry =
customer_details.address.countryที่
Stripe collect ตอน checkout (มาจาก card billing address)
Rule: ใช้ band ที่สูงกว่าเสมอ. ไม่ downgrade.
const BAND_ORDER: KarmaBand[] = ["neighbor", "baseline", "premium"];
export function resolveBandForBilling(
geoCountry: string | null,
billingCountry: string | null,
): KarmaBand {
if (!geoCountry && !billingCountry) return "premium"; // conservative
if (!geoCountry) return bandForCountry(billingCountry!);
if (!billingCountry) return bandForCountry(geoCountry);
const geoBand = bandForCountry(geoCountry);
const billingBand = bandForCountry(billingCountry);
return bandRank(billingBand) > bandRank(geoBand) ? billingBand : geoBand;
}ทำไมไม่ใช้ billing เป็นหลักเสมอ?
เพราะ legitimate cases:
- VN dev ที่ทำงานให้บริษัท US ใช้ US business card → ถ้าใช้
billing-only เขาจ่าย premium price แม้จะอยู่ในเวียดนามจริงๆ
- Cross-border worker SG ↔ MY — Malaysian dev อยู่ Singapore
ใช้ Malaysian card
ทางที่ดีกว่า: take max() — VN-on-US-card → premium (US user แอบใช้ VN VPN ป้องกันได้), แต่ VN-on-VN-card-in-VN → neighbor (legitimate, ไม่ลงโทษ).
Risk scoring (3-band)
แนวคิดเพิ่มเติม: band gap = |rank(geoBand) - rank(billingBand)|
const gap = Math.abs(rank(geoBand) - rank(billingBand));
if (gap === 0) return "low"; // same band, no concern
if (gap === 1) return "medium"; // neighbor↔baseline or baseline↔premium
return "high"; // neighbor↔premium = strong VPN signalStripe Radar rule:
Block charge if: charge_metadata['karma_risk_score'] == 'high'
Queue review if: 'medium'นี่จับ VPN + stolen-card combos ที่อาจ pass band check แต่ indicators อื่นน่าสงสัย.
Code — ใน production จริง
Schema
// lib/karma-pricing.ts
export type KarmaBand = "neighbor" | "baseline" | "premium";
export const KARMA_PRICES_THB: Record<KarmaBand, Record<TierKey, number>> = {
neighbor: { hobby: 99, pro: 299, business: 799 },
baseline: { hobby: 111, pro: 333, business: 888 }, // Thailand domestic
premium: { hobby: 149, pro: 399, business: 1_199 },
};
export const COUNTRY_TO_BAND: Record<string, KarmaBand> = {
// Neighbor — low-income SEA + South Asia
VN: "neighbor", ID: "neighbor", PH: "neighbor",
KH: "neighbor", LA: "neighbor", MM: "neighbor",
BD: "neighbor", PK: "neighbor", IN: "neighbor",
NP: "neighbor", LK: "neighbor",
// Baseline — home market
TH: "baseline",
// Premium — default for unlisted countries (conservative)
};Runtime invariant test
export function assertAllPricesAbovePhase4Floor(): void {
const floor = { hobby: 51, pro: 167, business: 572 };
for (const band of Object.keys(KARMA_PRICES_THB) as KarmaBand[]) {
for (const tier of ["hobby", "pro", "business"] as TierKey[]) {
const p = KARMA_PRICES_THB[band][tier];
if (p <= floor[tier]) {
throw new Error(`Karma price ${band}/${tier} = ฿${p} below Phase 4 floor`);
}
}
}
}เรียกใน CI ทุก commit — ป้องกันราคาต่ำกว่า marginal cost หลัง migration.
Stripe Checkout integration
// app/api/billing/stripe-checkout/route.ts
const karma = resolveKarma(geoCountry, parsed.billingCountry);
const thb = KARMA_PRICES_THB[karma.resolvedBand][tier];
const session = await stripe().checkout.sessions.create({
mode: "subscription",
payment_method_types: ["card", "promptpay"],
// Force billing-address collection so webhook can verify karma
billing_address_collection: "required",
line_items: [{
price_data: {
currency: "thb",
unit_amount: thb * 100, // satang (round THB, no fractional baht)
recurring: { interval: "month" },
product_data: { name: `NirvaDeploy ${tier.name}`, ... },
},
quantity: 1,
}],
metadata: {
nirvadeploy_karma_resolved_band: karma.resolvedBand,
nirvadeploy_karma_geo_band: karma.geoBand,
nirvadeploy_karma_billing_band: karma.billingBand,
nirvadeploy_karma_risk_score: karma.riskScore,
nirvadeploy_karma_geo_country: karma.geoCountry,
},
});ลิงก์ session.url ถูก redirect user ไปหน้า Stripe-hosted checkout.
Webhook audit
// app/api/billing/webhook/route.ts
case "checkout.session.completed": {
const session = event.data.object as Stripe.Checkout.Session;
const actualBillingCountry = session.customer_details?.address?.country;
const declaredBand = session.metadata?.nirvadeploy_karma_resolved_band;
const declaredGeoCountry = session.metadata?.nirvadeploy_karma_geo_country;
// Mismatch flag: caller declared VN/neighbor but card is US-based
// → flag for manual review or "your band changed" notification
return {
kind: "activate-subscription",
karmaAudit: { declaredBand, declaredGeoCountry, actualBillingCountry, ... },
// ...
};
}Bitcoin Lightning — universal accessibility
โมเดลนี้ทำงานกับ Bitcoin Lightning เป็นพิเศษดี:
- No FX surprise — Lightning invoice quote เป็น sats ที่ amount lock
ตอนสร้าง invoice. user จ่าย exact amount → no rounding
- No regional payment friction — VN user ไม่ต้องมี Visa/Mastercard
(~15% ของ VN ผู้ใหญ่มีบัตรเครดิต). มี Lightning wallet ก็พอ.
- Lower fees for neighbor-band Hobby — Stripe fee ~3.65% + ฿11
= ฿14.61 บน ฿99 (15% ของ revenue!). Lightning fee ~฿1 (1%).
- OpenNode auto-converts to THB — เราไม่ถือ BTC, ภ.พ.30 ออกใน
สกุลบาทเสมอ
Sats per tier (spot ฿2,000,000/BTC, rounded UP)
| Band | Hobby THB | Pro THB | Business THB |
|---|---|---|---|
| Neighbor | 4,950 sat | 14,950 sat | 39,950 sat |
| Baseline | 5,550 sat | 16,650 sat | 44,400 sat |
| Premium | 7,450 sat | 19,950 sat | 59,950 sat |
Conversion ใช้ thbToBTC() ใน lib/crypto-pricing.ts — Math.ceil เพื่อไม่ undercharge.
ที่ Hobby neighbor tier:
- Stripe path: ฿99 − ฿14.61 = net ฿84.39 to us
- Lightning path: ฿99 − ฿1 = net ฿98 to us
- = +16% revenue retention on Lightning
นี่ทำให้ Karma + Lightning เปลี่ยน margin profile ของ neighbor markets ทั้งหมด.
Open questions + Phase 4 work
VPN evasion is an arms race
- เราจับได้ band-gap = 2 (neighbor↔premium), แต่ gap = 1
(neighbor↔baseline) อาจ false-positive cross-border workers
- Phase 3+: เพิ่ม device fingerprinting + payment-velocity (3 cards
with different countries in 24h = high signal)
Multi-currency settlement
- ปัจจุบันเก็บใน THB เสมอ (เพื่อ ภ.พ.30 simple). EU/US users เห็น
charge เป็น USD/EUR ใน statement (FX โดยธนาคารของเขา)
- Phase 4+: Stripe multi-currency settlement → charge ในสกุลของ
user → reduce card-decline rate ~3-5% in EU
Localized "Supporter" tier
- บางคนใน neighbor band อาจอยาก pay full premium rate เพื่อ
support — ยังไม่มี explicit option
- Phase 4+: เพิ่ม "Supporter" tier (name your price, floor
฿99, suggested ฿333) — heroic narrative
Currency display UX
- เราแสดง local-currency เป็น quote (
≈ $2.83 USD), settle THB จริง - ลูกค้าเห็น THB amount ในใบเสร็จ + bank statement (with bank's FX)
- ทดสอบ A/B: แสดง dual (THB + local) vs local-only — ดู conversion lift
Try it
ดูราคาที่คุณจะได้:
# Public endpoint — no auth needed
curl https://nirvadeploy.com/api/karma-pricing?country=VNหรือ visit /karma สำหรับ interactive band explorer.
Related reading
- `/karma` landing page — interactive band explorer
- Cost-per-user analysis (full doc) — สมการเต็ม
- Why Thai PaaS should accept Bitcoin — Lightning architecture
- NirvaDeploy vs Railway — competitive positioning
- World Bank GNI per capita 2024 — primary input for band mapping
สรุป: Karma Pricing ไม่ใช่ technique ใหม่ (Spotify, Adobe, JetBrains ทำคล้ายๆ ในรูปแบบของตัวเอง). สิ่งที่เราทำใหม่คือ explicit transparency — 3 bands, ทุก country mapping, ทุก risk-scoring rule, public ทาง /api/karma-pricing + /karma page.
ลูกค้าที่เห็นว่าเราคิดราคา fair-and-transparent มักจะ less price- sensitive. และตลาดพัฒนาแล้วที่รู้ว่าตัวเองช่วย subsidize นัก พัฒนาในเวียดนาม → มี second-order brand affinity ที่ flat-pricing ไม่ generate.
That's the karma.
ชอบบทความนี้?
ลอง NirvaDeploy ฟรี
Free tier ตลอดชีพ · ไม่ต้องใส่บัตร · Sign in ด้วย Line/Google
เริ่มเลย →