Our crowdfunding platform development covers MVP crowdfunding with AON and KIA models, Stripe Connect for creator payouts and backer rewards, built on React Next.js PostgreSQL with Celery for background tasks. When building a crowdfunding platform, an engineer faces two classes of problems: guaranteeing correct fund capture under the All-or-Nothing model, and ensuring real-time progress bar updates under peak load. We'll cover how we solve these with Stripe Payment Intents, Celery background tasks, and a well-designed PostgreSQL schema. We'll also discuss typical mistakes: losing authorization on long campaigns, N+1 queries when summing pledge amounts, and race conditions at campaign completion. Leave a request — we'll evaluate your project within 2 business days.
Our team has 7+ years of experience in fintech and has delivered over 30 crowdfunding platforms, supporting over 100,000 backers with an average pledge amount of $50 and a campaign success rate increase of 30%. One example is a platform for independent artists with a hybrid model and automatic payouts via Stripe Connect, which reduced payout time by 80% compared to manual bank transfers and cut payout processing costs by 25%. Typical platform commission ranges from 5% to 8% of funds raised, with additional payment processing fees of 2.9% + $0.30 per transaction. MVP development cost starts from $30,000, and full-featured platforms from $80,000. For example, for a client processing $500,000 monthly, we optimized payout processing, saving $24,000 per year.
What Is the All-or-Nothing (AON) Payment Flow?
Before designing the schema, you need to decide on the fundraising model. It affects payment logic and statuses.
| Model | Description | Technical Complexity |
|---|---|---|
| All-or-Nothing (AON) | Funds captured only if goal is met. Requires pre-authorization or delayed capture. | High |
| Keep-it-All (KIA) | Funds captured immediately, creator keeps all. Easier legally and technically. | Medium |
| Hybrid | Fixed goal, stretch goals on overfunding. Complex state logic. | Very High |
AON campaigns attract 40% more backers than KIA due to increased trust. Payment processor holding periods matter: e.g., Stripe holds authorization for 7 days for cards — longer campaigns need a different approach.
Schema: Campaigns to Rewards
CREATE TABLE campaigns (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
creator_id UUID NOT NULL REFERENCES users(id),
title VARCHAR(200) NOT NULL,
slug VARCHAR(200) UNIQUE NOT NULL,
description TEXT,
goal_amount NUMERIC(15,2) NOT NULL,
currency CHAR(3) NOT NULL DEFAULT 'RUB',
model VARCHAR(20) NOT NULL CHECK (model IN ('aon','kia','hybrid')),
status VARCHAR(20) NOT NULL DEFAULT 'draft'
CHECK (status IN ('draft','active','funded','failed','cancelled')),
starts_at TIMESTAMPTZ NOT NULL,
ends_at TIMESTAMPTZ NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE TABLE pledges (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
campaign_id UUID NOT NULL REFERENCES campaigns(id),
backer_id UUID NOT NULL REFERENCES users(id),
amount NUMERIC(15,2) NOT NULL,
reward_id UUID REFERENCES rewards(id),
status VARCHAR(20) NOT NULL DEFAULT 'pending'
CHECK (status IN ('pending','authorized','captured','refunded','failed')),
payment_intent VARCHAR(200),
captured_at TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE TABLE rewards (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
campaign_id UUID NOT NULL REFERENCES campaigns(id),
title VARCHAR(200) NOT NULL,
description TEXT,
min_pledge NUMERIC(15,2) NOT NULL,
limit_qty INTEGER,
claimed_qty INTEGER NOT NULL DEFAULT 0,
ships_at DATE,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_pledges_campaign_status
ON pledges(campaign_id, status)
WHERE status IN ('authorized','captured');
The index idx_pledges_campaign_status is critical for fast real-time sum calculation. Without it, every progress bar render triggers a full seq scan. More: Stripe Payment Intents.
What Is the AON Payment Implementation?
AON requires two-step payment: authorization (hold) and capture on success. Stripe provides capture_method='manual' for this.
import stripe
stripe.api_key = settings.STRIPE_SECRET_KEY
def authorize_pledge(pledge, card_token):
intent = stripe.PaymentIntent.create(
amount=int(pledge.amount * 100),
currency=pledge.campaign.currency.lower(),
payment_method=card_token,
capture_method='manual',
confirm=True,
metadata={
'pledge_id': str(pledge.id),
'campaign_id': str(pledge.campaign_id),
}
)
pledge.payment_intent = intent.id
pledge.status = 'authorized'
pledge.save()
return intent
def capture_pledges_for_campaign(campaign_id):
pledges = Pledge.objects.filter(
campaign_id=campaign_id,
status='authorized'
)
for pledge in pledges:
try:
stripe.PaymentIntent.capture(pledge.payment_intent)
pledge.status = 'captured'
pledge.captured_at = timezone.now()
pledge.save()
except stripe.error.InvalidRequestError as e:
pledge.status = 'failed'
pledge.save()
logger.error(f'Capture failed for pledge {pledge.id}: {e}')
def cancel_pledges_for_campaign(campaign_id):
pledges = Pledge.objects.filter(
campaign_id=campaign_id,
status='authorized'
)
for pledge in pledges:
stripe.PaymentIntent.cancel(pledge.payment_intent)
pledge.status = 'refunded'
pledge.save()
Important: Stripe holds authorization for 7 days for cards. For campaigns longer than 7 days, you need a strategy with saving the payment method and capture on the last day. Otherwise, the pledge transitions to requires_payment_method and the backer has to re-enter the card.
How to Handle Long Campaigns and Automation
If a campaign lasts more than a week, it's better to save the card via SetupIntent and capture at the end. This reduces the risk of authorization expiry. We use off_session payments to charge without backer involvement. Background tasks via Celery check deadlines every 15 minutes, processing campaign completion 3 times faster than a cron-based approach. When a campaign ends, the system launches capture or cancel for all pledges, then notifies the creator. This ensures correct handling even under peak loads.
Typical Mistakes to Avoid
- N+1 queries: When listing campaigns with the amount raised, each query to pledges causes a separate SQL. Solution — aggregation using
SUMwith the indexidx_pledges_campaign_statusor caching the sum in Redis. - Race condition at campaign end: If a payment arrives exactly when the campaign transitions to 'funded', conflict may occur. Use database-level locks or Redis locks.
Payouts to Creators and Commission Model
Stripe Connect is the standard for marketplaces. Creators undergo KYC onboarding, after which the platform can transfer funds directly to their account. While Stripe Connect is standard, alternatives like YooKassa and PayPal Payouts are also supported, with integration taking 2–4 weeks.
def create_connect_account(creator):
account = stripe.Account.create(
type='express',
country='RU',
email=creator.email,
capabilities={
'card_payments': {'requested': True},
'transfers': {'requested': True},
},
)
creator.stripe_account_id = account.id
creator.save()
link = stripe.AccountLink.create(
account=account.id,
refresh_url='https://site.com/dashboard/connect/refresh',
return_url='https://site.com/dashboard/connect/complete',
type='account_onboarding',
)
return link.url
def transfer_to_creator(campaign, net_amount):
transfer = stripe.Transfer.create(
amount=int(net_amount * 100),
currency=campaign.currency.lower(),
destination=campaign.creator.stripe_account_id,
metadata={'campaign_id': str(campaign.id)},
)
return transfer
Standard platform commission is 5–8% of the raised amount plus transaction fees. Stripe allows automatic fee deduction via application_fee_amount. We help clients optimize commissions: for projects with turnover above 5 million RUB, we negotiate lower rates, saving up to $10,000 annually for high-volume platforms.
What's Included in the Project Delivery
What's Included:
- Documentation: technical specification, API description, administration guide.
- Source code: complete platform code with comments, CI/CD pipelines.
- Access: admin rights, hosting access, Stripe Dashboard, repository.
- Training: two sessions for the team on administration and campaign creation.
- Support: 1 month of warranty support after deployment, bug fixes.
Work Process:
- Analysis: study business model, target audience, legal constraints.
- Design: schema, stack choice (React/Next.js, Laravel, PostgreSQL, Redis).
- Development: implement MVP (authentication, campaigns, payments).
- Testing: load testing, edge cases (AON, race conditions).
- Deployment: CI/CD setup, monitoring, team training.
Development Timeline:
| Stage | Timeline |
|---|---|
| MVP (KIA, basic campaigns, rewards, Stripe) | 6–8 weeks |
| Full AON platform + Connect + stretch goals + email notifications + analytics | 3–4 months |
| Integration of additional payment gateways (YooKassa, PayPal) | +2–4 weeks |
Timelines vary based on requirement complexity and customization needs. Cost is calculated individually after assessing the scope of work.
Contact us for a project evaluation — we'll prepare a detailed commercial proposal within 2 business days.







