Skip to content

Latest commit

 

History

36 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 

Repository files navigation

BulkFlow

BulkFlow is a private, Google-authenticated CSV processing application deployed as one Cloudflare Worker at:

https://bulkflow.suryansh.lol

The React frontend, API, background queue consumer, and live WebSocket endpoint are built and deployed together from frontend/.

What changed

  • Replaced the Vercel frontend and Render backend with one Cloudflare deployment.
  • Replaced Redis/BullMQ with Cloudflare Queues.
  • Replaced MongoDB runtime storage with Cloudflare D1.
  • Replaced temporary server files with streamed Cloudflare R2 objects.
  • Replaced Socket.IO with a hibernating Durable Object WebSocket.
  • Removed email entry, password flows, OTP, SMTP, and completion emails.
  • Added Google Identity Services as the only sign-in method.
  • Added private per-user history, live progress, validation errors, and infinite record browsing.

Architecture

  1. The browser creates an authenticated upload tracker in D1.
  2. The browser streams the raw CSV through the Worker into R2, with upload progress visible locally.
  3. The Worker publishes one small job to Cloudflare Queues.
  4. The queue consumer streams and parses the R2 object, writing compact 75-row JSON chunks to D1.
  5. A hibernating Durable Object broadcasts live progress to the authenticated browser.
  6. The source object is deleted from R2 after successful processing. The processed result remains in D1.

This design uses no Redis server, MongoDB connection, SMTP server, or permanently running process.

Cloudflare resources

The production resources are already created and bound in frontend/wrangler.jsonc:

Binding Resource Purpose
DB D1 bulkflow-db Users, upload metadata, errors, and processed row chunks
UPLOADS R2 bulkflow-uploads Temporary source CSV storage
UPLOAD_QUEUE Queue bulkflow-jobs Background CSV processing
PROGRESS_ROOMS Durable Object ProgressRoom Live progress WebSockets

The queue is configured for one job per consumer invocation, up to two concurrent jobs, and automatic retries using the Free plan's platform execution limits.

Environment and secrets

Browser build variable

frontend/.env.production:

VITE_GOOGLE_CLIENT_ID=your-web-client-id.apps.googleusercontent.com

This value is public by design and is embedded into the browser bundle.

Worker secrets

Store these in Cloudflare, never in Git:

npx wrangler secret put GOOGLE_CLIENT_ID
npx wrangler secret put SESSION_SECRET

GOOGLE_CLIENT_ID must exactly match VITE_GOOGLE_CLIENT_ID. SESSION_SECRET should be at least 32 random bytes. Both production secrets are installed during deployment.

For local development, copy frontend/.dev.vars.example to frontend/.dev.vars and fill both values. Copy frontend/.env.example to frontend/.env.local for the browser-side client ID.

No Google client secret is used. If one was shared in chat or elsewhere, rotate it in Google Cloud because it is unnecessary for this flow.

Google OAuth configuration

In Google Cloud Console, open the Web OAuth client and add these Authorized JavaScript origins:

http://localhost:5173
https://bulkflow.suryansh.lol

No redirect URI is required because the app verifies the Google ID token on the Worker.

Local development

Use Node.js 22.19 or newer.

cd frontend
npm ci
npm run db:migrate:local
npm run dev

Open http://localhost:5173.

Validation and deployment

cd frontend
npm test
npm run build
npx wrangler deploy --dry-run
npm run db:migrate:remote
npm run deploy

The custom domain is declared in wrangler.jsonc, so Wrangler manages the Worker custom-domain binding for bulkflow.suryansh.lol.

CSV rules and free-tier boundaries

  • Accepted format: UTF-8 CSV.
  • Maximum source file size: 95 MB, below Cloudflare's 100 MB Free-plan request ceiling.
  • Quoted commas, escaped quotes, CRLF, and multiline quoted fields are supported.
  • Blank header names are normalized and duplicate headers receive numeric suffixes.
  • Rows with a different column count are reported and skipped.
  • Up to the first 100 row errors are retained for display.
  • Excel files must be exported to CSV. The previous backend advertised .xlsx but only parsed CSV.

Cloudflare's Free plan has usage ceilings rather than a Vercel-style expiring deployment. Current major allowances include 100,000 Worker requests/day, 10,000 Queue operations/day, 100,000 D1 rows written/day, 5 million D1 rows read/day, and 10 GB-month of R2 Standard storage. If a daily ceiling is reached, service for that product resumes when the allowance resets.

Security notes

  • Google ID tokens are verified against Google's JWKS, issuer, audience, and verified-email claim.
  • Sessions are signed, one-hour, HTTP-only, SameSite=Lax cookies.
  • Google login uses double-submit CSRF protection.
  • Every upload, WebSocket, history query, result page, and deletion is ownership-checked.
  • State-changing API requests reject foreign origins.
  • Source files are private R2 objects and are deleted after successful processing.
  • Secrets and local Cloudflare state are ignored by Git.

MongoDB note

Atlas database-user credentials can create a logical database inside an existing cluster, but they cannot create a new Atlas cluster. Creating a cluster requires Atlas account access or an Atlas Administration API service account. A separate bulkflow logical database was initialized in the provided existing cluster as requested. BulkFlow production intentionally uses D1, so the Worker does not need a MongoDB runtime connection or another paid/always-on service.

About

Bulk Flow — 85,000+ row Excel/CSV ingestion pipeline on Cloudflare Workers, Queues, D1 and R2, with live per-row progress streamed over a hibernating Durable Object.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages