mirror of
https://github.com/supabase/supabase.git
synced 2026-10-14 13:49:09 +03:00
refactor(pricing): derive pricing display strings from the shared-data catalog
This commit is contained in:
1 parent
58ff906e4b
commit
ec8ed5f573
6 files changed
+203
-92
No files matched your search
@@ -5,6 +5,7 @@ import { useTheme } from 'next-themes'
|
||||
import Image from 'next/image'
|
||||
import Link from 'next/link'
|
||||
import { FC } from 'react'
|
||||
import { ADDONS, usd } from 'shared-data/pricing-catalog'
|
||||
import { Button, cn } from 'ui'
|
||||
|
||||
import CostControlAnimation from './CostControlAnimation'
|
||||
@@ -26,7 +27,7 @@ const addons = [
|
||||
name: 'Custom Domain',
|
||||
heroImg: 'custom-domain-on',
|
||||
icon: 'custom-domain-upgrade',
|
||||
price: 'Flat fee $10/month',
|
||||
price: `Flat fee ${usd(ADDONS.customDomain.priceMonthlyPerDomain)}/month`,
|
||||
description:
|
||||
'Use your own domain for your Supabase project to present a branded experience to your users.',
|
||||
ctaText: 'Documentation',
|
||||
@@ -38,7 +39,7 @@ const addons = [
|
||||
name: 'Point in Time Recovery',
|
||||
heroImg: 'pitr-on',
|
||||
icon: 'pitr-upgrade',
|
||||
price: 'Starts from $100/month',
|
||||
price: `Starts from ${usd(ADDONS.pitr.priceMonthlyPer7DaysRetention)}/month`,
|
||||
description: 'Roll back to any specific point in time, down to the second.',
|
||||
ctaText: 'Documentation',
|
||||
ctaLink: 'https://supabase.com/docs/guides/platform/backups',
|
||||
|
||||
@@ -5,6 +5,7 @@ import Link from 'next/link'
|
||||
import React, { useEffect, useRef, useState } from 'react'
|
||||
import { useWindowSize } from 'react-use'
|
||||
import { plans as allPlans } from 'shared-data/plans'
|
||||
import { PLAN_BILLING, usd } from 'shared-data/pricing-catalog'
|
||||
import { Button, cn } from 'ui'
|
||||
import { ToggleGroup, ToggleGroupItem } from 'ui/src/components/shadcn/ui/toggle-group'
|
||||
|
||||
@@ -98,7 +99,7 @@ const PricingComputeSection = () => {
|
||||
</>
|
||||
)}
|
||||
<p className="text-foreground-lighter text-xs mt-2">
|
||||
Paid plans include $10/mo in compute credits, enough to cover one Micro instance.
|
||||
{`Paid plans include ${usd(PLAN_BILLING.pro.computeCreditsMonthly)}/mo in compute credits, enough to cover one Micro instance.`}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,28 +1,26 @@
|
||||
import { Button } from 'ui'
|
||||
import Panel from '../Panel'
|
||||
import Link from 'next/link'
|
||||
import { ArrowUpRight } from 'lucide-react'
|
||||
import Link from 'next/link'
|
||||
import { DISK_PRICING, qty, usd } from 'shared-data/pricing-catalog'
|
||||
import { Button } from 'ui'
|
||||
|
||||
const diskTypes = [
|
||||
{
|
||||
name: 'General Purpose',
|
||||
tagline: 'Balance between price and performance',
|
||||
maxSize: '16 TB',
|
||||
size: '8 GB included\nthen $0.125 per GB',
|
||||
iops: '3,000 IOPS included\nthen $0.024 per IOPS',
|
||||
throughput: '125 MB/s included\nthen $0.095 per MB/s',
|
||||
durability: '99.9%',
|
||||
},
|
||||
{
|
||||
name: 'High Performance',
|
||||
tagline: 'For mission critical applications',
|
||||
maxSize: '60 TB',
|
||||
size: '$0.195 per GB',
|
||||
iops: '$0.119 per IOPS',
|
||||
throughput: 'Scales automatically with IOPS',
|
||||
durability: '99.999%',
|
||||
},
|
||||
]
|
||||
import Panel from '../Panel'
|
||||
|
||||
const diskTypes = Object.values(DISK_PRICING).map((disk) => ({
|
||||
name: disk.displayName,
|
||||
tagline: disk.tagline,
|
||||
maxSize: `${disk.maxSizeTb} TB`,
|
||||
size: disk.includedPerProject
|
||||
? `${disk.includedPerProject.sizeGb} GB included\nthen ${usd(disk.perUnitMonth.sizeGb)} per GB`
|
||||
: `${usd(disk.perUnitMonth.sizeGb)} per GB`,
|
||||
iops: disk.includedPerProject
|
||||
? `${qty(disk.includedPerProject.iops, 'comma')} IOPS included\nthen ${usd(disk.perUnitMonth.iops)} per IOPS`
|
||||
: `${usd(disk.perUnitMonth.iops)} per IOPS`,
|
||||
throughput:
|
||||
disk.includedPerProject && disk.perUnitMonth.throughputMBps !== null
|
||||
? `${disk.includedPerProject.throughputMBps} MB/s included\nthen ${usd(disk.perUnitMonth.throughputMBps)} per MB/s`
|
||||
: (disk.throughputNote ?? ''),
|
||||
durability: `${disk.durabilityPercent}%`,
|
||||
}))
|
||||
|
||||
const PricingDiskSection = () => (
|
||||
<div>
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { ADDONS, gbDisplay, METERS, PLAN_BILLING, qty, usd, withUnit } from './pricing-catalog'
|
||||
|
||||
export type PlanId = 'free' | 'pro' | 'team' | 'enterprise'
|
||||
|
||||
export interface PricingInformation {
|
||||
@@ -27,16 +29,19 @@ export const plans: PricingInformation[] = [
|
||||
costUnit: '/ month',
|
||||
href: 'https://supabase.com/dashboard/new?plan=free',
|
||||
priceLabel: '',
|
||||
priceMonthly: 0,
|
||||
priceMonthly: PLAN_BILLING.free.priceMonthly,
|
||||
description: 'Perfect for passion projects & simple websites.',
|
||||
preface: 'Get started with:',
|
||||
features: [
|
||||
'Unlimited API requests',
|
||||
'50,000 monthly active users',
|
||||
['500 MB database size', 'Shared CPU • 500 MB RAM'],
|
||||
['5 GB egress'],
|
||||
['5 GB cached egress'],
|
||||
'1 GB file storage',
|
||||
`${qty(METERS.maus.includedByPlan.free, 'comma')} monthly active users`,
|
||||
[
|
||||
`${gbDisplay(METERS.databaseDiskSize.includedByPlan.free)} database size`,
|
||||
'Shared CPU • 500 MB RAM',
|
||||
],
|
||||
[`${qty(METERS.egress.includedByPlan.free)} GB egress`],
|
||||
[`${qty(METERS.cachedEgress.includedByPlan.free)} GB cached egress`],
|
||||
`${qty(METERS.storageSize.includedByPlan.free)} GB file storage`,
|
||||
'Community support',
|
||||
],
|
||||
footer: 'Free projects are paused after 1 week of inactivity. Limit of 2 active projects.',
|
||||
@@ -51,18 +56,36 @@ export const plans: PricingInformation[] = [
|
||||
href: 'https://supabase.com/dashboard/new?plan=pro',
|
||||
priceLabel: 'From',
|
||||
warning: 'Includes one project running on Micro compute.',
|
||||
priceMonthly: 25,
|
||||
priceMonthly: PLAN_BILLING.pro.priceMonthly,
|
||||
description: 'For production applications with the power to scale.',
|
||||
features: [
|
||||
['100,000 monthly active users', 'then $0.00325 per MAU'],
|
||||
['8 GB disk size per project', 'then $0.125 per GB'],
|
||||
['250 GB egress', 'then $0.09 per GB'],
|
||||
['250 GB cached egress', 'then $0.03 per GB'],
|
||||
['100 GB file storage', 'then $0.0213 per GB'],
|
||||
[
|
||||
`${qty(METERS.maus.includedByPlan.pro, 'comma')} monthly active users`,
|
||||
`then ${usd(METERS.maus.price)} per MAU`,
|
||||
],
|
||||
[
|
||||
`${gbDisplay(METERS.databaseDiskSize.includedByPlan.pro)} disk size per project`,
|
||||
`then ${usd(METERS.databaseDiskSize.price)} per GB`,
|
||||
],
|
||||
[
|
||||
`${withUnit(METERS.egress.includedByPlan.pro, 'GB')} egress`,
|
||||
`then ${usd(METERS.egress.price)} per GB`,
|
||||
],
|
||||
[
|
||||
`${withUnit(METERS.cachedEgress.includedByPlan.pro, 'GB')} cached egress`,
|
||||
`then ${usd(METERS.cachedEgress.price)} per GB`,
|
||||
],
|
||||
[
|
||||
`${withUnit(METERS.storageSize.includedByPlan.pro, 'GB')} file storage`,
|
||||
`then ${usd(METERS.storageSize.price)} per GB`,
|
||||
],
|
||||
'Email support',
|
||||
'Daily backups stored for 7 days',
|
||||
'7-day log retention',
|
||||
['Add Log Drains', 'additional $60 per drain, per project'],
|
||||
[
|
||||
'Add Log Drains',
|
||||
`additional ${usd(ADDONS.logDrain.priceMonthlyPerDrain)} per drain, per project`,
|
||||
],
|
||||
],
|
||||
preface: 'Everything in the Free Plan, plus:',
|
||||
cta: 'Get Started',
|
||||
@@ -76,7 +99,7 @@ export const plans: PricingInformation[] = [
|
||||
href: 'https://supabase.com/dashboard/new?plan=team',
|
||||
priceLabel: 'From',
|
||||
warning: 'Includes one project running on Micro compute.',
|
||||
priceMonthly: 599,
|
||||
priceMonthly: PLAN_BILLING.team.priceMonthly,
|
||||
description: 'Add features such as SSO, control over backups, and industry certifications.',
|
||||
features: [
|
||||
'SOC2 & ISO 27001',
|
||||
|
||||
@@ -53,18 +53,24 @@ export function qty(n: number, style?: 'comma' | 'millionWord'): string {
|
||||
return String(n)
|
||||
}
|
||||
|
||||
const THIN_SPACE = ' '
|
||||
|
||||
export function withUnit(n: number, unit: string, style?: 'comma' | 'millionWord'): string {
|
||||
return `${qty(n, style)}${THIN_SPACE}${unit}`
|
||||
}
|
||||
|
||||
export function gbDisplay(sizeGb: number): string {
|
||||
return sizeGb < 1 ? `${sizeGb * 1000} MB` : `${sizeGb} GB`
|
||||
return sizeGb < 1 ? withUnit(sizeGb * 1000, 'MB') : withUnit(sizeGb, 'GB')
|
||||
}
|
||||
|
||||
const GP3_PER_GB_MONTH = 0.125
|
||||
|
||||
export const PLAN_BILLING: Record<PlanKey, PlanBillingEntry> = {
|
||||
export const PLAN_BILLING = {
|
||||
free: { priceMonthly: 0, computeCreditsMonthly: null, spendCapAvailable: false },
|
||||
pro: { priceMonthly: 25, computeCreditsMonthly: 10, spendCapAvailable: true },
|
||||
team: { priceMonthly: 599, computeCreditsMonthly: 10, spendCapAvailable: false },
|
||||
enterprise: { priceMonthly: null, computeCreditsMonthly: null, spendCapAvailable: false },
|
||||
}
|
||||
} as const satisfies Record<PlanKey, PlanBillingEntry>
|
||||
|
||||
export const DISK_PRICING: Record<'gp3' | 'io2', DiskTypeEntry> = {
|
||||
gp3: {
|
||||
|
||||
+131
-49
@@ -1,3 +1,5 @@
|
||||
import { ADDONS, gbDisplay, METERS, qty, usd, withUnit } from './pricing-catalog'
|
||||
|
||||
type Pricing = {
|
||||
database: PricingCategory
|
||||
auth: PricingCategory
|
||||
@@ -122,9 +124,15 @@ export const pricing: Pricing = {
|
||||
key: 'database.size',
|
||||
title: 'Database size',
|
||||
plans: {
|
||||
free: '500 MB database size per project included',
|
||||
pro: ['8 GB disk size per project included', 'then $0.125 per GB'],
|
||||
team: ['8 GB disk size per project included', 'then $0.125 per GB'],
|
||||
free: `${gbDisplay(METERS.databaseDiskSize.includedByPlan.free)} database size per project included`,
|
||||
pro: [
|
||||
`${gbDisplay(METERS.databaseDiskSize.includedByPlan.pro)} disk size per project included`,
|
||||
`then ${usd(METERS.databaseDiskSize.price)} per GB`,
|
||||
],
|
||||
team: [
|
||||
`${gbDisplay(METERS.databaseDiskSize.includedByPlan.team)} disk size per project included`,
|
||||
`then ${usd(METERS.databaseDiskSize.price)} per GB`,
|
||||
],
|
||||
enterprise: 'Custom',
|
||||
},
|
||||
usage_based: true,
|
||||
@@ -156,9 +164,9 @@ export const pricing: Pricing = {
|
||||
title: 'Point in time recovery',
|
||||
plans: {
|
||||
free: false,
|
||||
pro: '$100 per month per 7 days retention',
|
||||
team: '$100 per month per 7 days retention',
|
||||
enterprise: '$100 per month per 7 days retention, >28 days retention available',
|
||||
pro: `${usd(ADDONS.pitr.priceMonthlyPer7DaysRetention)} per month per 7 days retention`,
|
||||
team: `${usd(ADDONS.pitr.priceMonthlyPer7DaysRetention)} per month per 7 days retention`,
|
||||
enterprise: `${usd(ADDONS.pitr.priceMonthlyPer7DaysRetention)} per month per 7 days retention, >28 days retention available`,
|
||||
},
|
||||
usage_based: false,
|
||||
},
|
||||
@@ -178,8 +186,8 @@ export const pricing: Pricing = {
|
||||
title: 'Branching',
|
||||
plans: {
|
||||
free: false,
|
||||
pro: '$0.01344 per branch, per hour',
|
||||
team: '$0.01344 per branch, per hour',
|
||||
pro: `${usd(METERS.branching.price)} per branch, per hour`,
|
||||
team: `${usd(METERS.branching.price)} per branch, per hour`,
|
||||
enterprise: 'Custom',
|
||||
},
|
||||
usage_based: true,
|
||||
@@ -188,9 +196,15 @@ export const pricing: Pricing = {
|
||||
key: 'database.egress',
|
||||
title: 'Egress',
|
||||
plans: {
|
||||
free: '5 GB included',
|
||||
pro: ['250 GB included', 'then $0.09 per GB'],
|
||||
team: ['250 GB included', 'then $0.09 per GB'],
|
||||
free: `${withUnit(METERS.egress.includedByPlan.free, 'GB')} included`,
|
||||
pro: [
|
||||
`${withUnit(METERS.egress.includedByPlan.pro, 'GB')} included`,
|
||||
`then ${usd(METERS.egress.price)} per GB`,
|
||||
],
|
||||
team: [
|
||||
`${withUnit(METERS.egress.includedByPlan.team, 'GB')} included`,
|
||||
`then ${usd(METERS.egress.price)} per GB`,
|
||||
],
|
||||
enterprise: 'Custom',
|
||||
},
|
||||
usage_based: true,
|
||||
@@ -201,14 +215,14 @@ export const pricing: Pricing = {
|
||||
plans: {
|
||||
free: false,
|
||||
pro: [
|
||||
'$0.053 per pipeline per hour',
|
||||
'$3.00 per GB processed during ongoing replication',
|
||||
'$0.60 per GB processed during initial sync',
|
||||
`${usd(METERS.replicationPipelineHours.price)} per pipeline per hour`,
|
||||
`${usd(METERS.replicationOngoingGb.price, 2)} per GB processed during ongoing replication`,
|
||||
`${usd(METERS.replicationInitialSyncGb.price, 2)} per GB processed during initial sync`,
|
||||
],
|
||||
team: [
|
||||
'$0.053 per pipeline per hour',
|
||||
'$3.00 per GB processed during ongoing replication',
|
||||
'$0.60 per GB processed during initial sync',
|
||||
`${usd(METERS.replicationPipelineHours.price)} per pipeline per hour`,
|
||||
`${usd(METERS.replicationOngoingGb.price, 2)} per GB processed during ongoing replication`,
|
||||
`${usd(METERS.replicationInitialSyncGb.price, 2)} per GB processed during initial sync`,
|
||||
],
|
||||
enterprise: 'Custom',
|
||||
},
|
||||
@@ -235,9 +249,15 @@ export const pricing: Pricing = {
|
||||
key: 'auth.maus',
|
||||
title: 'MAUs',
|
||||
plans: {
|
||||
free: '50,000 included',
|
||||
pro: ['100,000 included', 'then $0.00325 per MAU'],
|
||||
team: ['100,000 included', 'then $0.00325 per MAU'],
|
||||
free: `${qty(METERS.maus.includedByPlan.free, 'comma')} included`,
|
||||
pro: [
|
||||
`${qty(METERS.maus.includedByPlan.pro, 'comma')} included`,
|
||||
`then ${usd(METERS.maus.price)} per MAU`,
|
||||
],
|
||||
team: [
|
||||
`${qty(METERS.maus.includedByPlan.team, 'comma')} included`,
|
||||
`then ${usd(METERS.maus.price)} per MAU`,
|
||||
],
|
||||
enterprise: 'Custom',
|
||||
},
|
||||
usage_based: true,
|
||||
@@ -325,8 +345,14 @@ export const pricing: Pricing = {
|
||||
title: 'Advanced Multi-Factor Auth - Phone',
|
||||
plans: {
|
||||
free: false,
|
||||
pro: ['$75 per month for first project', 'then $10 per month per additional projects'],
|
||||
team: ['$75 per month for first project', 'then $10 per month per additional projects'],
|
||||
pro: [
|
||||
`${usd(ADDONS.advancedMfaPhone.priceMonthlyFirstProject)} per month for first project`,
|
||||
`then ${usd(ADDONS.advancedMfaPhone.priceMonthlyAdditionalProject)} per month per additional projects`,
|
||||
],
|
||||
team: [
|
||||
`${usd(ADDONS.advancedMfaPhone.priceMonthlyFirstProject)} per month for first project`,
|
||||
`then ${usd(ADDONS.advancedMfaPhone.priceMonthlyAdditionalProject)} per month per additional projects`,
|
||||
],
|
||||
enterprise: 'Custom',
|
||||
},
|
||||
usage_based: false,
|
||||
@@ -335,9 +361,15 @@ export const pricing: Pricing = {
|
||||
key: 'auth.thirdPartyMAUs',
|
||||
title: 'Third-Party MAUs',
|
||||
plans: {
|
||||
free: '50,000 included',
|
||||
pro: ['100,000 included', 'then $0.00325 per MAU'],
|
||||
team: ['100,000 included', 'then $0.00325 per MAU'],
|
||||
free: `${qty(METERS.thirdPartyMaus.includedByPlan.free, 'comma')} included`,
|
||||
pro: [
|
||||
`${qty(METERS.thirdPartyMaus.includedByPlan.pro, 'comma')} included`,
|
||||
`then ${usd(METERS.thirdPartyMaus.price)} per MAU`,
|
||||
],
|
||||
team: [
|
||||
`${qty(METERS.thirdPartyMaus.includedByPlan.team, 'comma')} included`,
|
||||
`then ${usd(METERS.thirdPartyMaus.price)} per MAU`,
|
||||
],
|
||||
enterprise: 'Custom',
|
||||
},
|
||||
usage_based: true,
|
||||
@@ -347,8 +379,14 @@ export const pricing: Pricing = {
|
||||
title: 'Single Sign-On (SAML 2.0)',
|
||||
plans: {
|
||||
free: false,
|
||||
pro: ['50 included', 'then $0.015 per MAU'],
|
||||
team: ['50 included', 'then $0.015 per MAU'],
|
||||
pro: [
|
||||
`${qty(METERS.ssoMaus.includedByPlan.pro)} included`,
|
||||
`then ${usd(METERS.ssoMaus.price)} per MAU`,
|
||||
],
|
||||
team: [
|
||||
`${qty(METERS.ssoMaus.includedByPlan.team)} included`,
|
||||
`then ${usd(METERS.ssoMaus.price)} per MAU`,
|
||||
],
|
||||
enterprise: 'Contact Us',
|
||||
},
|
||||
|
||||
@@ -420,9 +458,15 @@ export const pricing: Pricing = {
|
||||
key: 'storage.size',
|
||||
title: 'Storage',
|
||||
plans: {
|
||||
free: '1 GB included',
|
||||
pro: ['100 GB included', 'then $0.0213 per GB'],
|
||||
team: ['100 GB included', 'then $0.0213 per GB'],
|
||||
free: `${withUnit(METERS.storageSize.includedByPlan.free, 'GB')} included`,
|
||||
pro: [
|
||||
`${withUnit(METERS.storageSize.includedByPlan.pro, 'GB')} included`,
|
||||
`then ${usd(METERS.storageSize.price)} per GB`,
|
||||
],
|
||||
team: [
|
||||
`${withUnit(METERS.storageSize.includedByPlan.team, 'GB')} included`,
|
||||
`then ${usd(METERS.storageSize.price)} per GB`,
|
||||
],
|
||||
enterprise: 'Custom',
|
||||
},
|
||||
usage_based: true,
|
||||
@@ -431,9 +475,15 @@ export const pricing: Pricing = {
|
||||
key: 'storage.cachedEgress',
|
||||
title: 'Cached Egress',
|
||||
plans: {
|
||||
free: '5 GB included',
|
||||
pro: ['250 GB included', 'then $0.03 per GB'],
|
||||
team: ['250 GB included', 'then $0.03 per GB'],
|
||||
free: `${withUnit(METERS.cachedEgress.includedByPlan.free, 'GB')} included`,
|
||||
pro: [
|
||||
`${withUnit(METERS.cachedEgress.includedByPlan.pro, 'GB')} included`,
|
||||
`then ${usd(METERS.cachedEgress.price)} per GB`,
|
||||
],
|
||||
team: [
|
||||
`${withUnit(METERS.cachedEgress.includedByPlan.team, 'GB')} included`,
|
||||
`then ${usd(METERS.cachedEgress.price)} per GB`,
|
||||
],
|
||||
enterprise: 'Custom',
|
||||
},
|
||||
usage_based: true,
|
||||
@@ -476,8 +526,14 @@ export const pricing: Pricing = {
|
||||
title: 'Image Transformations',
|
||||
plans: {
|
||||
free: false,
|
||||
pro: ['100 origin images included', 'then $5 per 1000 origin images'],
|
||||
team: ['100 origin images included', 'then $5 per 1000 origin images'],
|
||||
pro: [
|
||||
`${qty(METERS.imageTransformations.includedByPlan.pro)} origin images included`,
|
||||
`then ${usd(METERS.imageTransformations.price)} per ${qty(METERS.imageTransformations.per)} origin images`,
|
||||
],
|
||||
team: [
|
||||
`${qty(METERS.imageTransformations.includedByPlan.team)} origin images included`,
|
||||
`then ${usd(METERS.imageTransformations.price)} per ${qty(METERS.imageTransformations.per)} origin images`,
|
||||
],
|
||||
enterprise: 'Custom',
|
||||
},
|
||||
usage_based: true,
|
||||
@@ -492,9 +548,15 @@ export const pricing: Pricing = {
|
||||
key: 'functions.invocations',
|
||||
title: 'Invocations',
|
||||
plans: {
|
||||
free: '500,000 included',
|
||||
pro: ['2 Million included', 'then $2 per 1 Million'],
|
||||
team: ['2 Million included', 'then $2 per 1 Million'],
|
||||
free: `${qty(METERS.functionsInvocations.includedByPlan.free, 'comma')} included`,
|
||||
pro: [
|
||||
`${qty(METERS.functionsInvocations.includedByPlan.pro, 'millionWord')} included`,
|
||||
`then ${usd(METERS.functionsInvocations.price)} per ${qty(METERS.functionsInvocations.per, 'millionWord')}`,
|
||||
],
|
||||
team: [
|
||||
`${qty(METERS.functionsInvocations.includedByPlan.team, 'millionWord')} included`,
|
||||
`then ${usd(METERS.functionsInvocations.price)} per ${qty(METERS.functionsInvocations.per, 'millionWord')}`,
|
||||
],
|
||||
enterprise: 'Custom',
|
||||
},
|
||||
usage_based: true,
|
||||
@@ -520,9 +582,15 @@ export const pricing: Pricing = {
|
||||
key: 'realtime.concurrentConnections',
|
||||
title: 'Concurrent Peak Connections',
|
||||
plans: {
|
||||
free: '200 included',
|
||||
pro: ['500 included', 'then $10 per 1000'],
|
||||
team: ['500 included', 'then $10 per 1000'],
|
||||
free: `${qty(METERS.realtimeConnections.includedByPlan.free)} included`,
|
||||
pro: [
|
||||
`${qty(METERS.realtimeConnections.includedByPlan.pro)} included`,
|
||||
`then ${usd(METERS.realtimeConnections.price)} per ${qty(METERS.realtimeConnections.per)}`,
|
||||
],
|
||||
team: [
|
||||
`${qty(METERS.realtimeConnections.includedByPlan.team)} included`,
|
||||
`then ${usd(METERS.realtimeConnections.price)} per ${qty(METERS.realtimeConnections.per)}`,
|
||||
],
|
||||
enterprise: 'Custom concurrent connections and volume discount',
|
||||
},
|
||||
usage_based: true,
|
||||
@@ -531,9 +599,15 @@ export const pricing: Pricing = {
|
||||
key: 'realtime.messagesPerMonth',
|
||||
title: 'Messages Per Month',
|
||||
plans: {
|
||||
free: '2 Million included',
|
||||
pro: ['5 Million included', 'then $2.50 per Million'],
|
||||
team: ['5 Million included', 'then $2.50 per Million'],
|
||||
free: `${qty(METERS.realtimeMessages.includedByPlan.free, 'millionWord')} included`,
|
||||
pro: [
|
||||
`${qty(METERS.realtimeMessages.includedByPlan.pro, 'millionWord')} included`,
|
||||
`then ${usd(METERS.realtimeMessages.price, 2)} per Million`,
|
||||
],
|
||||
team: [
|
||||
`${qty(METERS.realtimeMessages.includedByPlan.team, 'millionWord')} included`,
|
||||
`then ${usd(METERS.realtimeMessages.price, 2)} per Million`,
|
||||
],
|
||||
enterprise: 'Volume discounts on messages',
|
||||
},
|
||||
usage_based: true,
|
||||
@@ -599,8 +673,16 @@ export const pricing: Pricing = {
|
||||
title: 'Log Drain',
|
||||
plans: {
|
||||
free: false,
|
||||
pro: ['$60 per drain per month', '+ $0.20 per million events', '+ $0.09 per GB egress'],
|
||||
team: ['$60 per drain per month', '+ $0.20 per million events', '+ $0.09 per GB egress'],
|
||||
pro: [
|
||||
`${usd(ADDONS.logDrain.priceMonthlyPerDrain)} per drain per month`,
|
||||
`+ ${usd(ADDONS.logDrain.perMillionEvents, 2)} per million events`,
|
||||
`+ ${usd(ADDONS.logDrain.perGbEgress)} per GB egress`,
|
||||
],
|
||||
team: [
|
||||
`${usd(ADDONS.logDrain.priceMonthlyPerDrain)} per drain per month`,
|
||||
`+ ${usd(ADDONS.logDrain.perMillionEvents, 2)} per million events`,
|
||||
`+ ${usd(ADDONS.logDrain.perGbEgress)} per GB egress`,
|
||||
],
|
||||
enterprise: 'Custom',
|
||||
},
|
||||
usage_based: true,
|
||||
@@ -720,9 +802,9 @@ export const pricing: Pricing = {
|
||||
title: 'Custom Domains',
|
||||
plans: {
|
||||
free: false,
|
||||
pro: '$10 per domain per month per project add on',
|
||||
team: '$10 per domain per month per project add on',
|
||||
enterprise: '1, additional $10/domain/month',
|
||||
pro: `${usd(ADDONS.customDomain.priceMonthlyPerDomain)} per domain per month per project add on`,
|
||||
team: `${usd(ADDONS.customDomain.priceMonthlyPerDomain)} per domain per month per project add on`,
|
||||
enterprise: `1, additional ${usd(ADDONS.customDomain.priceMonthlyPerDomain)}/domain/month`,
|
||||
},
|
||||
usage_based: false,
|
||||
},
|
||||
|
||||
Reference in new issue
Block a user