DEV Community

Sufal Thakre
Sufal Thakre

Posted on

Building GigFlow: A Real-Time Freelance Marketplace with Secure Hiring Logic

Modern marketplaces aren’t just about CRUD APIs — they’re about correctness, trust, and real-time feedback. In this post, I’ll walk through how I built GigFlow, a full-stack freelance marketplace where clients can post jobs, freelancers can bid, and hiring happens atomically and in real time.

Demo Video:

This project focuses heavily on:

  • Secure authentication
  • Correct hiring logic
  • Preventing race conditions
  • Real-time updates using Socket.io

🚀 What is GigFlow?

GigFlow is a mini freelance marketplace where:

  • Any authenticated user can post a gig (client role)
  • Any user can bid on gigs (freelancer role)
  • A client can hire exactly one freelancer per gig
  • All other bids are automatically rejected
  • The hired freelancer gets a real-time notification

The core challenge wasn’t the UI — it was ensuring data integrity and correctness under concurrency.


🧱 Tech Stack

Frontend

  • React (Vite)
  • Tailwind CSS
  • Context API for state management
  • Socket.io Client
  • Fetch API with credentials

Backend

  • Node.js + Express
  • MongoDB + Mongoose
  • JWT Authentication (HttpOnly cookies)
  • Socket.io
  • MongoDB Transactions

Deployment

  • Frontend: Vercel
  • Backend: Render
  • Database: MongoDB Atlas

🔐 Authentication (JWT + HttpOnly Cookies)

Authentication is handled using JWT stored in HttpOnly cookies, which:

  • Prevents access from JavaScript (XSS-safe)
  • Works cleanly with credentials: "include"

Each request:

  • Verifies the JWT
  • Attaches the authenticated user to req.user

This enables role-less design — users can act as both client and freelancer without separate accounts.


📦 Core Data Models

User

{
  name,
  email,
  password
}
Enter fullscreen mode Exit fullscreen mode

Gig

{
  title,
  description,
  budget,
  ownerId,
  status: "open" | "assigned",
  assignedTo
}
Enter fullscreen mode Exit fullscreen mode

Bid

{
  gigId,
  freelancerId,
  message,
  price,
  status: "pending" | "hired" | "rejected"
}
Enter fullscreen mode Exit fullscreen mode

🧠 The Hiring Problem (The Hard Part)

The most important rule:

Only one freelancer can be hired for a gig — ever.

Edge case:

  • Two clients (or two tabs) click Hire at the same time
  • Without protection, two bids could be marked as hired

This is where many systems fail.


🔒 Solving Race Conditions with MongoDB Transactions

The hire logic is wrapped inside a MongoDB session + transaction.

High-level flow:

  1. Start a session
  2. Check if the gig is still open
  3. Update gig → assigned
  4. Mark selected bid → hired
  5. Mark all other bids → rejected
  6. Commit transaction

If any step fails, everything rolls back.

This guarantees:

  • Exactly one hired freelancer
  • No partial or inconsistent state

⚡ Real-Time Updates with Socket.io

Once a freelancer is hired:

  • The backend emits a hired event to that freelancer’s socket room
  • The freelancer’s dashboard updates instantly

No polling. No refresh. Instant feedback.


🖥️ Frontend Flow

Client

  • Create gig
  • View bids
  • Click Hire
  • Gig becomes assigned

Freelancer

  • Submit bids
  • Track bid status
  • Receive real-time hire notification

State is kept minimal and predictable using Context API.


🌍 Deployment Lessons

Backend (Render)

  • Environment variables must be explicitly set
  • CORS must allow the deployed frontend domain
  • Socket.io needs the same CORS config as Express

Frontend (Vercel)

  • API base URL must point to deployed backend
  • Fetch requests must include credentials

🧪 What This Project Demonstrates

  • Correct API design
  • Secure authentication
  • Transactional integrity
  • Real-time communication
  • Production deployment awareness

This is not a “todo app” — it’s a system designed to behave correctly under pressure.


🔗 Links


🧠 Final Thoughts

The hardest part of full-stack development isn’t writing code — it’s making sure the system behaves correctly when multiple things happen at once.

GigFlow was built with that principle in mind.

Top comments (0)