nirva|deploy
2026-05-16·13 min read·NirvaDeploy team
#pricing#global-saas#PPP#business-model#Thai-tech#Bitcoin#geo-equity
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 — อ่านง่าย, จำง่าย, ไม่ต้องอธิบายทศนิยม.

BandHobbyProBusinessSubsidy class
🌏 Neighbor฿99฿299฿799Subsidized
🇹🇭 Baseline฿111฿333฿888Baseline (Thailand domestic)
💎 Premium฿149฿399฿1,199Supporter

ทำไม 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:

  1. GNI per capita (primary)
  2. PPP (Purchasing Power Parity)
  3. Card-fraud rate per region (Stripe Radar data)
  4. 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):

TierComputeStripeOverheadTotal
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):

TierTotal 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):

BandNRevenue/moPhase 1-3 CostPhase 4 Margin
Neighbor350฿34,650฿70,350+฿16,800
Baseline400฿44,400฿80,400+฿24,000
Premium250฿37,250฿50,250+฿24,500
Total1,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):

MetricFlat ฿111Karma 3-band
Phase 1-3 Hobby revenue฿111,000฿116,300 (+5%)
Phase 1-3 cost coverage55%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:

  1. geoCountry = X-Vercel-IP-Country หรือ CF-IPCountry

(จาก CDN edge — บอกว่า user มาจาก IP ของ network ไหน)

  1. 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 signal

Stripe 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)

BandHobby THBPro THBBusiness THB
Neighbor4,950 sat14,950 sat39,950 sat
Baseline5,550 sat16,650 sat44,400 sat
Premium7,450 sat19,950 sat59,950 sat

Conversion ใช้ thbToBTC() ใน lib/crypto-pricing.tsMath.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 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

เริ่มเลย →