From ac85811fe99ffd04fe5041488f17239a33b2f068 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kevin=20Gr=C3=BCneberg?= Date: Fri, 1 Sep 2023 14:25:50 +0200 Subject: [PATCH] feat: launch org-based billing --- .../pages/guides/platform/compute-add-ons.mdx | 50 +++---- .../Pricing/ComputePricingModal.tsx | 28 +++- apps/www/data/PricingAddOnTable.json | 20 +-- apps/www/pages/pricing/index.tsx | 69 ++++++++-- packages/shared-data/plans.ts | 43 ++---- packages/shared-data/pricing.ts | 23 +--- studio/pages/new-with-subscription.tsx | 123 ------------------ 7 files changed, 135 insertions(+), 221 deletions(-) delete mode 100644 studio/pages/new-with-subscription.tsx diff --git a/apps/docs/pages/guides/platform/compute-add-ons.mdx b/apps/docs/pages/guides/platform/compute-add-ons.mdx index d3bd4ad528a..e809e93476a 100644 --- a/apps/docs/pages/guides/platform/compute-add-ons.mdx +++ b/apps/docs/pages/guides/platform/compute-add-ons.mdx @@ -8,21 +8,23 @@ export const meta = { Every project on the Supabase Platform comes with its own dedicated Postgres instance running inside a virtual machine (VM). The following table describes the base instance with additional compute add-ons available if you need extra performance when scaling up Supabase. -| Plan | Pricing | CPU | Memory | Connections: Direct | Connections: Pooler | -| --------------- | ------- | ----------------------- | ------ | ------------------- | ------------------- | -| Free (Included) | $0 | 2-core ARM (shared) | 1 GB | 60 | 200 | -| Small | $5 | 2-core ARM (shared) | 2 GB | 90 | 200 | -| Medium | $50 | 2-core ARM (shared) | 4 GB | 120 | 200 | -| Large | $100 | 2-core ARM (dedicated) | 8 GB | 160 | 300 | -| XL | $200 | 4-core ARM (dedicated) | 16 GB | 240 | 700 | -| 2XL | $400 | 8-core ARM (dedicated) | 32 GB | 380 | 1500 | -| 4XL | $950 | 16-core ARM (dedicated) | 64 GB | 480 | 3000 | -| 8XL | $1,860 | 32-core ARM (dedicated) | 128 GB | 490 | 6000 | -| 12XL | $2,790 | 48-core ARM (dedicated) | 192 GB | 500 | 9000 | -| 16XL | $3,720 | 64-core ARM (dedicated) | 256 GB | 500 | 12,000 | +| Plan | Hourly Price USD | Monthly Price USD | CPU | Memory | Connections: Direct | Connections: Pooler | +| ------- | ---------------- | ----------------- | ----------------------- | ------ | ------------------- | ------------------- | +| Starter | $0.01344 | ~$10 | 2-core ARM (shared) | 1 GB | 60 | 200 | +| Small | $0.0206 | ~$15 | 2-core ARM (shared) | 2 GB | 90 | 200 | +| Medium | $0.0822 | ~$60 | 2-core ARM (shared) | 4 GB | 120 | 200 | +| Large | $0.1517 | ~$110 | 2-core ARM (dedicated) | 8 GB | 160 | 300 | +| XL | $0.2877 | ~$210 | 4-core ARM (dedicated) | 16 GB | 240 | 700 | +| 2XL | $0.562 | ~$410 | 8-core ARM (dedicated) | 32 GB | 380 | 1500 | +| 4XL | $1.32 | ~$960 | 16-core ARM (dedicated) | 64 GB | 480 | 3000 | +| 8XL | $2.562 | ~$1,870 | 32-core ARM (dedicated) | 128 GB | 490 | 6000 | +| 12XL | $3.836 | ~$2,800 | 48-core ARM (dedicated) | 192 GB | 500 | 9000 | +| 16XL | $5.12 | ~$3,730 | 64-core ARM (dedicated) | 256 GB | 500 | 12,000 | Number of connections above are recommended values. +We charge hourly for additional compute based on your usage. Read more about [usage-based billing for compute](/docs/guides/platform/org-based-billing#usage-based-billing-for-compute). + [Contact us](https://supabase.com/contact/enterprise) if you require a custom plan. ## Dedicated vs. shared CPU @@ -37,18 +39,18 @@ When considering compute upgrades, assess whether your bottlenecks are hardware- SSD Disks are attached to your servers and the disk performance depends on the compute add-on of your instance. Disk IO refers to two metrics: throughput (Megabits per Second) and IOPS (Input/Output Operations per Second). -| Plan | Pricing | Max Disk Throughput | Baseline Disk Throughput | Max IOPS | Baseline IOPS | -| --------------- | ------- | ------------------- | ------------------------ | ----------- | ------------- | -| Free (Included) | $0 | 2,085 Mbps | 87 Mbps | 11,800 IOPS | 500 IOPS | -| Small | $5 | 2,085 Mbps | 174 Mbps | 11,800 IOPS | 1,000 IOPS | -| Medium | $50 | 2,085 Mbps | 347 Mbps | 11,800 IOPS | 2,000 IOPS | -| Large | $100 | 4,750 Mbps | 630 Mbps | 20,000 IOPS | 3,600 IOPS | -| XL | $200 | 4,750 Mbps | 1,188 Mbps | 20,000 IOPS | 6,000 IOPS | -| 2XL | $400 | 4,750 Mbps | 2,375 Mbps | 20,000 IOPS | 12,000 IOPS | -| 4XL | $950 | 4,750 Mbps | 4,750 Mbps | 20,000 IOPS | 20,000 IOPS | -| 8XL | $1,860 | 9,500 Mbps | 9,500 Mbps | 40,000 IOPS | 40,000 IOPS | -| 12XL | $2,790 | 14,250 Mbps | 14,250 Mbps | 50,000 IOPS | 50,000 IOPS | -| 16XL | $3,720 | 19,000 Mbps | 19,000 Mbps | 80,000 IOPS | 80,000 IOPS | +| Plan | Max Disk Throughput | Baseline Disk Throughput | Max IOPS | Baseline IOPS | +| ------- | ------------------- | ------------------------ | ----------- | ------------- | +| Starter | 2,085 Mbps | 87 Mbps | 11,800 IOPS | 500 IOPS | +| Small | 2,085 Mbps | 174 Mbps | 11,800 IOPS | 1,000 IOPS | +| Medium | 2,085 Mbps | 347 Mbps | 11,800 IOPS | 2,000 IOPS | +| Large | 4,750 Mbps | 630 Mbps | 20,000 IOPS | 3,600 IOPS | +| XL | 4,750 Mbps | 1,188 Mbps | 20,000 IOPS | 6,000 IOPS | +| 2XL | 4,750 Mbps | 2,375 Mbps | 20,000 IOPS | 12,000 IOPS | +| 4XL | 4,750 Mbps | 4,750 Mbps | 20,000 IOPS | 20,000 IOPS | +| 8XL | 9,500 Mbps | 9,500 Mbps | 40,000 IOPS | 40,000 IOPS | +| 12XL | 14,250 Mbps | 14,250 Mbps | 50,000 IOPS | 50,000 IOPS | +| 16XL | 19,000 Mbps | 19,000 Mbps | 80,000 IOPS | 80,000 IOPS | [Contact us](https://supabase.com/contact/enterprise) if you require a custom plan. diff --git a/apps/www/components/Pricing/ComputePricingModal.tsx b/apps/www/components/Pricing/ComputePricingModal.tsx index 7e4149fcd13..4da3e700122 100644 --- a/apps/www/components/Pricing/ComputePricingModal.tsx +++ b/apps/www/components/Pricing/ComputePricingModal.tsx @@ -1,9 +1,10 @@ import React, { Fragment, useMemo } from 'react' import { useRouter } from 'next/router' import { useTheme } from 'common/Providers' -import { IconCheckCircle, IconXCircle, Modal } from 'ui' +import { IconXCircle, Modal } from 'ui' import pricingAddOn from '~/data/PricingAddOnTable.json' import { IconPricingIncludedCheck, IconPricingMinus } from './PricingIcons' +import Link from 'next/link' interface Props { showComputeModal: boolean @@ -47,12 +48,33 @@ export default function ComputePricingModal({ showComputeModal, setShowComputeMo

Choose best compute setup for you

-

+

Every project on the Supabase Platform comes with its own dedicated Postgres instance running inside a virtual machine (VM). The following table describes the base instance with additional compute add-ons available if you need extra performance when scaling up Supabase.

+

+ Compute instances are billed hourly and you can scale up or down at any time if you + need extra performance. You'll only be charged at the end of the month for the hours + you've used. Paid plans come with $10 in Compute Credits to cover one Starter + instance or parts of any other instance. Read more on{' '} + + + usage-based billing for compute + + {' '} + or{' '} + + + Compute Add-ons + + + . +

@@ -73,7 +95,7 @@ export default function ComputePricingModal({ showComputeModal, setShowComputeMo {i === 0 && ( - Included in Free and Pro plan + First instance is free on paid plans )} diff --git a/apps/www/data/PricingAddOnTable.json b/apps/www/data/PricingAddOnTable.json index 23b617c339f..76e4b495ffe 100644 --- a/apps/www/data/PricingAddOnTable.json +++ b/apps/www/data/PricingAddOnTable.json @@ -11,7 +11,7 @@ { "columns": [ { "key": "plan", "title": "Plan", "value": "Starter" }, - { "key": "pricing", "title": "Pricing", "value": "$0" }, + { "key": "pricing", "title": "Price USD", "value": "$10" }, { "key": "cpu", "title": "CPU", "value": "2-core ARM" }, { "key": "dedicated", "title": "Dedicated", "value": false }, { "key": "memory", "title": "Memory", "value": "1 GB" }, @@ -36,7 +36,7 @@ { "columns": [ { "key": "plan", "title": "Plan", "value": "Small" }, - { "key": "pricing", "title": "Pricing", "value": "$5" }, + { "key": "pricing", "title": "Price USD", "value": "$15" }, { "key": "cpu", "title": "CPU", "value": "2-core ARM" }, { "key": "dedicated", "title": "Dedicated", "value": false }, { "key": "memory", "title": "Memory", "value": "2 GB" }, @@ -61,7 +61,7 @@ { "columns": [ { "key": "plan", "title": "Plan", "value": "Medium" }, - { "key": "pricing", "title": "Pricing", "value": "$50" }, + { "key": "pricing", "title": "Price USD", "value": "$60" }, { "key": "cpu", "title": "CPU", "value": "2-core ARM" }, { "key": "dedicated", "title": "Dedicated", "value": false }, { "key": "memory", "title": "Memory", "value": "4 GB" }, @@ -86,7 +86,7 @@ { "columns": [ { "key": "plan", "title": "Plan", "value": "Large" }, - { "key": "pricing", "title": "Pricing", "value": "$100" }, + { "key": "pricing", "title": "Price USD", "value": "$110" }, { "key": "cpu", "title": "CPU", "value": "2-core ARM" }, { "key": "dedicated", "title": "Dedicated", "value": true }, { "key": "memory", "title": "Memory", "value": "8 GB" }, @@ -111,7 +111,7 @@ { "columns": [ { "key": "plan", "title": "Plan", "value": "XL" }, - { "key": "pricing", "title": "Pricing", "value": "$200" }, + { "key": "pricing", "title": "Price USD", "value": "$210" }, { "key": "cpu", "title": "CPU", "value": "4-core ARM" }, { "key": "dedicated", "title": "Dedicated", "value": true }, { "key": "memory", "title": "Memory", "value": "16 GB" }, @@ -136,7 +136,7 @@ { "columns": [ { "key": "plan", "title": "Plan", "value": "2XL" }, - { "key": "pricing", "title": "Pricing", "value": "$400" }, + { "key": "pricing", "title": "Price USD", "value": "$410" }, { "key": "cpu", "title": "CPU", "value": "8-core ARM" }, { "key": "dedicated", "title": "Dedicated", "value": true }, { "key": "memory", "title": "Memory", "value": "32 GB" }, @@ -161,7 +161,7 @@ { "columns": [ { "key": "plan", "title": "Plan", "value": "4XL" }, - { "key": "pricing", "title": "Pricing", "value": "$950" }, + { "key": "pricing", "title": "Price USD", "value": "$960" }, { "key": "cpu", "title": "CPU", "value": "16-core ARM" }, { "key": "dedicated", "title": "Dedicated", "value": true }, { "key": "memory", "title": "Memory", "value": "64 GB" }, @@ -186,7 +186,7 @@ { "columns": [ { "key": "plan", "title": "Plan", "value": "8XL" }, - { "key": "pricing", "title": "Pricing", "value": "$1,860" }, + { "key": "pricing", "title": "Price USD", "value": "$1,870" }, { "key": "cpu", "title": "CPU", "value": "32-core ARM" }, { "key": "dedicated", "title": "Dedicated", "value": true }, { "key": "memory", "title": "Memory", "value": "128 GB" }, @@ -211,7 +211,7 @@ { "columns": [ { "key": "plan", "title": "Plan", "value": "12XL" }, - { "key": "pricing", "title": "Pricing", "value": "$2,790" }, + { "key": "pricing", "title": "Price USD", "value": "$2,800" }, { "key": "cpu", "title": "CPU", "value": "48-core ARM" }, { "key": "dedicated", "title": "Dedicated", "value": true }, { "key": "memory", "title": "Memory", "value": "192 GB" }, @@ -240,7 +240,7 @@ { "columns": [ { "key": "plan", "title": "Plan", "value": "16XL" }, - { "key": "pricing", "title": "Pricing", "value": "$3,720" }, + { "key": "pricing", "title": "Price USD", "value": "$3,730" }, { "key": "cpu", "title": "CPU", "value": "64-core ARM" }, { "key": "dedicated", "title": "Dedicated", "value": true }, { "key": "memory", "title": "Memory", "value": "256 GB" }, diff --git a/apps/www/pages/pricing/index.tsx b/apps/www/pages/pricing/index.tsx index f5e2c494805..f98ab1a0260 100644 --- a/apps/www/pages/pricing/index.tsx +++ b/apps/www/pages/pricing/index.tsx @@ -1,4 +1,4 @@ -import { Accordion, Button, IconCheck, Select } from 'ui' +import { Accordion, Badge, Button, IconCheck, Select } from 'ui' import Solutions from 'data/Solutions' import { NextSeo } from 'next-seo' import Link from 'next/link' @@ -13,6 +13,7 @@ import pricingFaq from '~/data/PricingFAQ.json' import { useTheme } from 'common/Providers' import ComputePricingModal from '~/components/Pricing/ComputePricingModal' import { plans } from 'shared-data/plans' +import { ArrowNarrowRightIcon } from '@heroicons/react/outline' export default function IndexPage() { const router = useRouter() @@ -121,7 +122,7 @@ export default function IndexPage() {

{priceDescription}

{description}

- + diff --git a/packages/shared-data/plans.ts b/packages/shared-data/plans.ts index 88a2830ee72..2f1d9b29839 100644 --- a/packages/shared-data/plans.ts +++ b/packages/shared-data/plans.ts @@ -11,7 +11,6 @@ export interface PricingInformation { description: string preface: string features: string[] - featuresOrg?: string[] footer?: string cta: string } @@ -21,12 +20,12 @@ export const plans: PricingInformation[] = [ id: 'tier_free', name: 'Free', nameBadge: '', - costUnit: '/ month / project', - costUnitOrg: '/ month', - href: 'https://supabase.com/dashboard/new/new-project', + costUnit: '/ month / org', + costUnitOrg: '/ month / org', + href: 'https://supabase.com/dashboard/new?plan=free', priceLabel: '', priceMonthly: 0, - warning: 'Limit of 2 free projects', + warning: 'Limit of 2 free organizations', description: 'Perfect for passion projects & simple websites.', preface: 'Get started with:', features: [ @@ -34,7 +33,7 @@ export const plans: PricingInformation[] = [ 'Social OAuth providers', 'Up to 500MB database space', 'Up to 1GB file storage', - 'Up to 2GB bandwidth', + 'Up to 5GB bandwidth', 'Up to 50MB file uploads', 'Up to 50,000 monthly active users', 'Up to 500K Edge Function invocations', @@ -50,34 +49,19 @@ export const plans: PricingInformation[] = [ id: 'tier_pro', name: 'Pro', nameBadge: '', - costUnit: '/ month / project', - costUnitOrg: '/ month', - href: 'https://supabase.com/dashboard/new/new-project', + costUnit: '/ month / org', + costUnitOrg: '/ month / org', + href: 'https://supabase.com/dashboard/new?plan=pro', priceLabel: 'From', warning: 'Usage-based plan', priceMonthly: 25, description: 'For production applications with the option to scale.', - featuresOrg: [ - '$10 Compute Credits', - 'No project pausing', - 'Daily backups stored for 7 days', - '8GB database space included', - '100GB file storage included', - '50GB bandwidth included', - '5GB file uploads included', - '100,000 monthly active users included', - '2M Edge Function invocations included', - '500 concurrent Realtime connections included', - '5 million Realtime messages included', - '7-day log retention', - 'Email support', - ], features: [ 'No project pausing', 'Daily backups stored for 7 days', '8GB database space included', '100GB file storage included', - '50GB bandwidth included', + '250GB bandwidth included', '5GB file uploads included', '100,000 monthly active users included', '2M Edge Function invocations included', @@ -94,9 +78,9 @@ export const plans: PricingInformation[] = [ id: 'tier_team', name: 'Team', nameBadge: 'New', - costUnit: '/ month', - costUnitOrg: '/ month', - href: 'https://forms.supabase.com/team', + costUnit: '/ month / org', + costUnitOrg: '/ month / org', + href: 'https://supabase.com/dashboard/new?plan=team', priceLabel: 'From', warning: 'Usage-based plan', priceMonthly: 599, @@ -113,7 +97,7 @@ export const plans: PricingInformation[] = [ ], footer: 'Additional fees apply for usage beyond included usage.', preface: 'Everything in the Pro plan, plus:', - cta: 'Contact Us', + cta: 'Get Started', }, { id: 'tier_enterprise', @@ -125,6 +109,7 @@ export const plans: PricingInformation[] = [ `SSO/SAML`, `On-premise support`, `24×7×365 premium enterprise support`, + 'Custom Security Questionnaires', `Private Slack channel`, ], priceLabel: '', diff --git a/packages/shared-data/pricing.ts b/packages/shared-data/pricing.ts index c8927d77ef0..59aa4cc5ef1 100644 --- a/packages/shared-data/pricing.ts +++ b/packages/shared-data/pricing.ts @@ -112,14 +112,14 @@ export const pricing: Pricing = { usage_based: false, }, { - title: 'Database egress', + title: 'Bandwidth', tooltips: { - main: 'Billing is based on the total sum of outgoing traffic of your database in GB throughout your billing period.', + main: 'Billing is based on the total sum of outgoing traffic (includes Database, Storage, Realtime, Auth) in GB throughout your billing period.', }, plans: { - free: '2GB included', - pro: '50 GB included, then $0.09 per GB', - team: '50 GB included, then $0.09 per GB', + free: '5GB included', + pro: '250 GB included, then $0.09 per GB', + team: '250 GB included, then $0.09 per GB', enterprise: 'Unlimited', }, usage_based: true, @@ -234,19 +234,6 @@ export const pricing: Pricing = { }, usage_based: true, }, - { - title: 'Storage egress', - tooltips: { - main: 'All requests to view and download your storage items go through our CDN. We sum up all outgoing traffic (egress) for storage related requests through our CDN. We do not differentiate between cache and no cache hits.\nBilling is based on the total amount of egress in GB throughout your billing period.', - }, - plans: { - free: '2 GB included', - pro: '200 GB included, then $0.09 per GB', - team: '200 GB included, then $0.09 per GB', - enterprise: 'Unlimited', - }, - usage_based: true, - }, { title: 'Custom access controls', plans: { diff --git a/studio/pages/new-with-subscription.tsx b/studio/pages/new-with-subscription.tsx deleted file mode 100644 index 3c34a7433ce..00000000000 --- a/studio/pages/new-with-subscription.tsx +++ /dev/null @@ -1,123 +0,0 @@ -import HCaptcha from '@hcaptcha/react-hcaptcha' -import { Elements } from '@stripe/react-stripe-js' -import { loadStripe } from '@stripe/stripe-js' -import { useTheme } from 'common' -import { observer } from 'mobx-react-lite' -import { useRouter } from 'next/router' -import { useCallback, useEffect, useState } from 'react' - -import { NewOrgForm } from 'components/interfaces/Organization' -import { WizardLayout } from 'components/layouts' -import { useSetupIntent } from 'data/stripe/setup-intent-mutation' -import { useFlag } from 'hooks' -import { STRIPE_PUBLIC_KEY } from 'lib/constants' -import { useIsHCaptchaLoaded } from 'stores/hcaptcha-loaded-store' -import { NextPageWithLayout } from 'types' - -const stripePromise = loadStripe(STRIPE_PUBLIC_KEY) - -/** - * No org selected yet, create a new one - */ -const Wizard: NextPageWithLayout = () => { - const router = useRouter() - const { isDarkMode } = useTheme() - - const [intent, setIntent] = useState() - const captchaLoaded = useIsHCaptchaLoaded() - - const orgCreationV2 = useFlag('orgcreationv2') - const [captchaToken, setCaptchaToken] = useState(null) - const [captchaRef, setCaptchaRef] = useState(null) - - const { mutate: setupIntent } = useSetupIntent({ onSuccess: (res) => setIntent(res) }) - - const captchaRefCallback = useCallback((node) => { - setCaptchaRef(node) - }, []) - - useEffect(() => { - if (orgCreationV2 === false) { - router.push('/new') - } - }, [orgCreationV2]) - - const initSetupIntent = async (hcaptchaToken: string | undefined) => { - if (!hcaptchaToken) return console.error('Hcaptcha token is required') - - // Force a reload of Elements, necessary for Stripe - setIntent(undefined) - setupIntent({ hcaptchaToken }) - } - - const options = { - clientSecret: intent ? intent.client_secret : '', - appearance: { theme: isDarkMode ? 'night' : 'flat', labels: 'floating' }, - } as any - - const loadPaymentForm = async () => { - if (captchaRef && captchaLoaded) { - let token = captchaToken - - try { - if (!token) { - const captchaResponse = await captchaRef.execute({ async: true }) - token = captchaResponse?.response ?? null - } - } catch (error) { - return - } - - await initSetupIntent(token ?? undefined) - resetCaptcha() - } - } - - useEffect(() => { - loadPaymentForm() - }, [captchaRef, captchaLoaded]) - - const resetSetupIntent = () => { - return loadPaymentForm() - } - - const onLocalCancel = () => { - setIntent(undefined) - } - - const resetCaptcha = () => { - setCaptchaToken(null) - captchaRef?.resetCaptcha() - } - - return ( - <> - { - setCaptchaToken(token) - }} - onClose={onLocalCancel} - onExpire={() => { - setCaptchaToken(null) - }} - /> - - {intent && ( - - resetSetupIntent()} /> - - )} - - ) -} - -Wizard.getLayout = (page) => ( - - {page} - -) - -export default observer(Wizard)