Skip to content
Al Shakib E Elahi
05Photo contests

Your Capture Awards

A contest platform for photographers - entries, judging and results, at photograph file sizes. I owned the backend, the storage pipeline and the deployment. The interesting part was never the CRUD; it was that a contest deadline creates a traffic shape most systems never see.

Year
2024
Role
Backend, API integration, deployment
Context
Client product
Category
Marketplace
Your Capture Awards homepage

The contest homepage.

01The problem

Photographers submit at the last possible minute, at full resolution. That produces a sharp upload spike against the deadline, with each request an order of magnitude larger than a typical API call. Routing those bytes through the application server would have made the deadline the outage.

02The approach

Uploads go directly to Amazon S3 rather than through the API, so the application handles metadata while S3 handles bytes. Email - entry confirmations, judging notices, results - runs through an Agenda-backed queue so a slow mail provider cannot stall a request. Socket.IO pushes contest and judging updates live, and the client uses RTK Query so repeated gallery views are served from cache instead of re-fetching.

03Architecture

How the pieces fit.

  1. API

    Express.js services for contests, entries and judging.

  2. Storage

    Amazon S3 for contest image uploads, keeping large objects off the app servers.

  3. Queue

    Agenda scheduling the email pipeline so delivery is decoupled from the request.

  4. Realtime

    Socket.IO for contest and judging notifications.

  5. Client data

    RTK Query for cache-aware fetching on the Next.js frontend.

  6. Edge

    Nginx reverse proxy on DigitalOcean, deployed via GitHub Actions.

04Tech stack
Next.jsExpress.jsMongoDBAmazon S3Socket.IOAgendaRTK QueryNginx

Deployment

  • GitHub Actions for CI/CD pipelines
  • Hosted on DigitalOcean, domain registered with Namecheap
  • Nginx as reverse proxy, TMUX for session management
05Key features
  • Direct-to-S3 uploads for full-resolution contest entries
  • Agenda-backed email queue for confirmations, judging notices and results
  • Real-time notifications keeping entrants updated during judging
  • RTK Query caching to keep gallery browsing cheap
06Challenges

The parts that were not obvious at the start.

  1. 01

    The deadline spike

    Submission traffic is not uniform - it is nearly all in the final hours. Moving uploads off the application path meant the spike hit object storage, which is built for it, instead of Node processes, which are not.

  2. 02

    Email that cannot block a request

    Contest emails go out in bursts to large recipient lists. Sending inline would have tied request latency to a third-party mail provider's worst day. Queueing through Agenda made delivery a background concern with retries.

07Results
  • Live at yourcaptureawards.com
  • Handles full-resolution submission bursts against contest deadlines
  • Automated deploys through GitHub Actions
08What I took from it
  • Never let user file bytes travel through your application server if object storage can take them directly.
  • Anything that talks to a third party belongs in a queue, not in the request.