Volca Review 2026: Multi-Tenant SaaS Boilerplate
TL;DR
Volca is a solid multi-tenant TypeScript boilerplate with a focus on production infrastructure. AWS Cognito for auth (unusual choice), Stripe billing, and a clean separation between frontend and backend. At ~$99-$149, it's cheaper than Supastarter for multi-tenancy. Trade-off: AWS lock-in and less polish than Supastarter.
What You Get
Price: ~$99-$149 (check volca.dev for current pricing)
Core features:
- React (Vite) + TypeScript (SPA, not SSR)
- Node.js/Express backend
- Multi-tenancy: Teams + roles
- Auth: AWS Cognito
- Payments: Stripe
- Database: PostgreSQL via Knex
- UI: Tailwind + custom components
- Infrastructure: Terraform for AWS
The Architecture Decision: SPA + API
Volca makes an unusual choice: React SPA (Vite) + Express API, rather than Next.js:
apps/
├── client/ ← React SPA (Vite)
├── api/ ← Express + TypeScript
└── infra/ ← Terraform (AWS)
This decoupled approach is appropriate for products that will have multiple clients (web + mobile + third-party) or teams that want strict separation between frontend and backend.
// apps/api/src/modules/projects/project.router.ts
import { Router } from 'express';
import { requireAuth } from '../auth/auth.middleware';
import { requireTeamAccess } from '../teams/team.middleware';
const router = Router();
router.get('/teams/:teamId/projects',
requireAuth,
requireTeamAccess('member'),
async (req, res) => {
const projects = await projectService.findByTeam(req.params.teamId);
return res.json(projects);
}
);
router.post('/teams/:teamId/projects',
requireAuth,
requireTeamAccess('admin'),
async (req, res) => {
const project = await projectService.create({
...req.body,
teamId: req.params.teamId,
});
return res.json(project);
}
);
export default router;
This is more REST-like than tRPC — useful for teams building public APIs or needing OpenAPI documentation.
AWS Cognito Auth
Volca uses AWS Cognito for authentication — unusual in the boilerplate space:
// AWS Cognito user pool setup
import { CognitoIdentityProviderClient, SignUpCommand } from '@aws-sdk/client-cognito-identity-provider';
const cognitoClient = new CognitoIdentityProviderClient({ region: 'us-east-1' });
export async function signUp(email: string, password: string) {
const command = new SignUpCommand({
ClientId: process.env.COGNITO_CLIENT_ID!,
Username: email,
Password: password,
UserAttributes: [{ Name: 'email', Value: email }],
});
return cognitoClient.send(command);
}
Why Cognito? It scales infinitely, handles MFA natively, and integrates with AWS IAM. The downside: AWS vendor lock-in and more complexity than Clerk or Supabase Auth.
Multi-Tenancy with Team Roles
// Team role enforcement
const requireTeamAccess = (minimumRole: 'member' | 'admin' | 'owner') =>
async (req: Request, res: Response, next: NextFunction) => {
const { teamId } = req.params;
const { userId } = req.auth!;
const membership = await db('team_memberships')
.where({ team_id: teamId, user_id: userId })
.first();
if (!membership) return res.status(403).json({ error: 'Not a team member' });
const roleHierarchy = { member: 0, admin: 1, owner: 2 };
if (roleHierarchy[membership.role] < roleHierarchy[minimumRole]) {
return res.status(403).json({ error: 'Insufficient permissions' });
}
req.teamMembership = membership;
next();
};
Terraform Infrastructure
Volca includes Terraform for AWS infrastructure:
# infrastructure/main.tf — AWS setup
module "api" {
source = "./modules/api"
environment = var.environment
api_version = var.api_version
database_url = module.database.connection_string
cognito_user_pool_id = module.auth.user_pool_id
}
module "database" {
source = "./modules/rds"
environment = var.environment
instance_class = "db.t3.micro" # Dev
# instance_class = "db.t3.medium" # Production
}
This is valuable for teams deploying to AWS who want infrastructure-as-code from day one.
Volca vs Supastarter
| Feature | Volca | Supastarter |
|---|---|---|
| Price | ~$99-149 | $299 |
| Multi-tenancy | ✅ | ✅ |
| Auth | AWS Cognito | Supabase Auth |
| Stack | SPA + API | Next.js |
| Infrastructure | Terraform/AWS | Vercel |
| i18n | ❌ | ✅ |
| Admin panel | ❌ | ✅ Basic |
| Lock-in | AWS | Supabase |
Volca is cheaper; Supastarter has more features and better documentation.
Who Should Buy Volca
Good fit:
- Teams deploying to AWS (uses Cognito, can use RDS)
- Products needing a REST API (not tRPC or server components)
- Teams who want Terraform infrastructure from the start
- Budget-conscious teams needing multi-tenancy
Bad fit:
- Vercel/Next.js teams (architecture mismatch)
- Teams wanting simpler auth than Cognito
- Founders needing the fastest time-to-market
- Teams who want Supabase ecosystem
Final Verdict
Rating: 3/5
Volca fills a niche: multi-tenant SaaS for AWS-native teams at a lower price than Supastarter. The architecture decisions (Cognito, SPA+API, Terraform) are defensible but create lock-in and complexity. For the right team (AWS shop, REST API preference, IaC requirement), it's a good fit.
Getting Started
# Clone and configure
git clone https://github.com/volca-io/volca.git my-app
cd my-app
# Install dependencies
npm install
# Configure environment
cp .env.example .env
# Set: COGNITO_USER_POOL_ID, COGNITO_CLIENT_ID, COGNITO_REGION
# DATABASE_URL (PostgreSQL)
# STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET
# JWT_SECRET
# Push database schema
npm run db:migrate
# Start development
npm run dev # Starts both client (Vite) and API (Express)
The decoupled architecture means two dev servers run simultaneously — Vite on port 3000 and Express on port 4000. This is the primary complexity increase vs a Next.js monolith.
Stripe Subscription Setup
// apps/api/src/modules/stripe/stripe.router.ts
router.post('/checkout', requireAuth, async (req, res) => {
const { planId } = req.body;
const team = await teamService.findByUserId(req.userId!);
const session = await stripe.checkout.sessions.create({
mode: 'subscription',
customer: team.stripeCustomerId,
line_items: [{ price: planId, quantity: 1 }],
success_url: `${process.env.FRONTEND_URL}/dashboard?upgrade=success`,
cancel_url: `${process.env.FRONTEND_URL}/pricing`,
metadata: { teamId: team.id },
});
return res.json({ url: session.url });
});
The subscription is attached to the team (not the individual user), enabling multi-user teams on a single subscription — the correct pattern for B2B SaaS.
Deploying with Terraform
Volca's Terraform modules provision the full AWS stack:
# Deploy to AWS
cd infrastructure
terraform init
terraform workspace new production
terraform apply -var-file="production.tfvars"
# What gets provisioned:
# - ECS task (Express API)
# - RDS PostgreSQL instance
# - Cognito User Pool
# - ALB (Application Load Balancer)
# - S3 bucket + CloudFront for React SPA
# - Route53 DNS records
This full IaC stack is Volca's differentiator. Most boilerplates document deployment; Volca automates it. The tradeoff is AWS lock-in and Terraform expertise required.
The AWS Cognito Trade-Off
AWS Cognito handles authentication at scale without operational overhead — it manages user pools, handles MFA, and integrates with AWS IAM for fine-grained access control. The cost is $0 for the first 50,000 MAU, then $0.0055 per MAU. At 100,000 active users, Cognito costs $275/month — comparable to Clerk at scale.
The downside: Cognito's API is verbose compared to Clerk or Better Auth. Password reset flows, MFA setup, and OAuth integrations require more code than equivalent Clerk functionality. The developer experience is lower, but the operational scalability is higher.
For AWS-native teams already using IAM roles, Cognito's integration with the rest of the AWS ecosystem justifies the complexity. For teams deploying outside AWS, Cognito's lock-in is a real cost.
Key Takeaways
- Volca is the right multi-tenant boilerplate for AWS-native teams — Cognito, RDS, Terraform IaC are all AWS-first
- The SPA + API architecture is more appropriate than Next.js for products planning public APIs or multiple client types
- Terraform infrastructure-as-code from day one eliminates manual AWS console configuration
- Team-level subscription billing (not user-level) is the correct B2B SaaS pattern — Volca implements this correctly
- The main trade-offs: AWS lock-in, dual dev server complexity, and lower developer experience vs Clerk-based alternatives
Volca for API-First Products
The SPA + Express architecture is a genuine advantage for one use case: products building a public API alongside the web app. Next.js API routes work well for private backend calls, but public REST APIs benefit from dedicated Express routing with explicit versioning, rate limiting, and OpenAPI documentation.
// Express API versioning — clean for public APIs
app.use('/api/v1', v1Router);
app.use('/api/v2', v2Router);
// Easy to add API key auth on top of session auth
router.get('/api/v1/projects',
apiKeyOrSessionAuth, // Accept both tokens and sessions
rateLimitPerApiKey,
async (req, res) => { ... }
);
If your product will have external integrations (Zapier, n8n, third-party apps), the dedicated API server makes versioning and rate limiting cleaner than Next.js route handlers.
This is the use case where Volca's architecture earns its complexity cost. For internal-only SaaS where the API is consumed solely by your own frontend, a Next.js monolith is simpler.
Volca is the only boilerplate in this price range that ships with both the REST API foundation and the Terraform IaC to deploy it to production. For AWS-committed teams building API-first products, this combination is difficult to match otherwise. The higher setup complexity is a one-time cost; the architectural clarity pays dividends as the API surface grows and the product matures into a platform that third-party developers can integrate with.
Volca's AWS Cognito Auth: What It Means in Practice
AWS Cognito is a managed user directory service. For products already committed to AWS, using Cognito instead of Clerk or NextAuth means user management lives inside your AWS account rather than a third-party service. This matters for teams with strict data residency requirements or organizations that consolidate vendor relationships inside AWS for billing and compliance purposes.
The practical difference for developers: Cognito's DX is significantly worse than Clerk. The configuration surface area is larger (User Pools, App Clients, Identity Pools, attributes), the error messages are less helpful, and the documentation requires more cross-referencing. Volca abstracts some of this complexity, but you'll encounter the Cognito layer when customizing auth flows (custom email templates, MFA configuration, attribute schema).
The AWS-native advantage is real in the other direction: Cognito integrates natively with API Gateway, Lambda authorizers, and IAM for machine-to-machine authentication. If your SaaS architecture uses API Gateway + Lambda for internal services, Cognito tokens work across all of them without an additional JWT verification library.
For teams choosing Volca: plan an extra half-day to understand Cognito's configuration model compared to what you'd spend with Clerk. The investment pays off if you're building a product that will use more AWS services over time.
The team management layer in Volca uses Cognito Groups to model organizations. Adding a user to a team adds them to a Cognito group. Access control in API handlers checks group membership via the JWT claims that Cognito includes in the access token. This is a clean pattern that avoids a separate authorization service for team-level permissions, though it couples your authorization model to Cognito's group structure.
Volca Compared to Supastarter and Makerkit
Volca occupies a narrow niche — AWS-native, multi-tenant, open-source — that other boilerplates don't directly compete with. The cleaner comparisons are against the architecture trade-offs rather than feature parity.
Volca vs Supastarter: Supastarter uses Supabase for auth and database, giving better DX and a managed service. Volca uses Cognito and RDS with Terraform, giving AWS-native infrastructure. For Vercel/Supabase shops: Supastarter. For AWS shops: Volca.
Volca vs Makerkit: Makerkit is Next.js first with React Query and a more conventional stack. It's better documented and has a larger user community. Choose Volca when the SPA + separate API architecture is a concrete requirement, not a preference.
Volca vs building from scratch on AWS: Volca's value is the Terraform configuration and the multi-tenancy model. Writing correct Terraform for a production SaaS from scratch takes 2-3 days for an experienced AWS engineer. Volca compresses that to hours. For teams with limited AWS infrastructure experience, the Terraform alone justifies the price.
The decision to commit to AWS through Volca is a meaningful one. Once your application, auth, and database are deployed via Cognito, RDS, and ECS, moving away from AWS is a multi-week migration project. Make this choice deliberately — it's the right call for teams already in the AWS ecosystem, and the wrong call for teams who want cloud portability or vendor independence. Volca's active maintenance keeps the Terraform and CDK configurations current with AWS service changes, which is a genuine time saver given how frequently AWS updates its IAM policies and service APIs, meaning the infrastructure investment compounds over the lifetime of the product.
Compare Volca with other multi-tenant boilerplates in our best open-source SaaS boilerplates guide.
See our Supastarter review for the feature-rich alternative with better documentation.
See our multi-tenancy patterns guide for the architectural considerations Volca addresses.
Check out this boilerplate
View Volcaon StarterPick →