I’m Kayla. I’ve built three real stores with Node.js. Different sizes. Different pain. Same late nights.
If you’re wondering, “Can Node carry my shop?” Short answer: yes. But it depends on the shape of your store and your team. Let me explain. If you want a zero-fluff deep dive into battle-tested Node patterns for commerce, I highly recommend this breakdown on ImprovingCode — it taught me tricks I now reach for daily.
Store #1: Medusa + Next.js for a Band Merch Shop
This was a scrappy build. Hoodies, vinyl, stickers. I ran Medusa (official site) as the backend (Node), and Next.js for the storefront. Stripe for payments. Shippo for labels. Postgres and Redis on Railway. Frontend on Vercel. Nothing fancy.
What worked great:
- I got a working store in a day. Seed data helped.
- Products had variants out of the box. Small, medium, large? Easy.
- The admin panel did the basics: orders, returns, swaps.
- Stripe plugin was solid. Refunds and captures were clean.
What made me groan:
- Shipping rules got weird. Free shipping on vinyl but not on hoodies? I wrote a custom fulfillment rule. It worked, but I felt the glue.
- Medusa updates moved fast. A minor upgrade broke my coupon code check once. Fix was small, but I had to read the code to see why.
- Webhooks needed care. I used BullMQ for queues so email didn’t block checkout. Worth it. Still, one missed env var and orders stuck. Ouch.
Real moment: Our Black Friday drop hit 1,200 orders in a weekend. One t3.medium box on AWS handled the backend fine with Redis cache. CPU spiked during drops only. I set rate limits with express-rate-limit and kept checkout smooth.
Would I do it again? For a small to mid shop, yes. It felt “Node-y” in a good way. I could read the code. I could patch stuff fast.
Store #2: Vendure (NestJS) for a B2B Catalog That Needed Rules
This one was not cute. It had price lists per customer, buy boxes, and a sales rep flow. I used Vendure (official site) (also Node, built on NestJS). Postgres on Supabase. Admin UI from Vendure. Frontend was a simple Next app with GraphQL.
What I loved:
- Strong TypeScript. I knew what each field was. Errors made sense.
- Promotions were flexible. We made “Buy 10, get 2 free for Warehouse Clients” without hacks.
- GraphQL API was clean. I could test it in the playground like a pro.
What tested my patience:
- The plugin dev flow felt heavier. NestJS makes you think in modules. Good for order. Slower for quick hacks.
- Build times were longer. Not bad, but I noticed on CI.
- Bulk import needed care. I wrote a script with csv-parse and used the import API. It worked, but it wasn’t plug-and-play.
Real issue: We sent order webhooks to an old ERP. The ERP would time out. Vendure retried, which was fine, but the ERP double-booked orders. I added idempotency keys and a BullMQ queue. Problem solved. Felt very “warehouse.”
Would I use it again? For B2B or complex pricing, yes. For a small shop? Probably overkill.
Store #3: A Custom Express Build for a Local Bakery
This one was fun. And a little silly. The bakery needed pickup slots, day-old deals after 3 p.m., and a “we ran out” button. Nothing fit clean. So I went custom: Express + Objection.js + PostgreSQL. Stripe for payments. Nodemailer for email. Hosted on Fly.io with Docker. PM2 for the process.
What worked sweet:
- I controlled the checkout flow. Pre-auth on Stripe until staff marked “Ready.” People liked it.
- The “day-old” logic was simple code, not a plugin fight.
- Fast pages. No heavy admin. Just what they needed.
What bit me:
- I had to build an admin. Even a small one takes time.
- Returns were manual. They wanted it that way, but still.
- I had to write tests. And yes, I broke things when I skipped them.
Real moment: On launch day, I fat-fingered a CORS rule. Checkout failed for Safari only. I fixed it in 10 minutes, but that ten felt like an hour. Keep a staging site. Please.
Would I repeat? Only when the rules are weird, the team is small, and time lines are short. It’s fast… until it’s not.
Payments, Emails, and All the Glue
- Stripe worked great in all three builds. Webhooks can drift, so log every event. I store Stripe IDs on orders. Saves me.
- PayPal was okay on Medusa. Sandbox was flaky. Live was fine.
- Email: I moved from SMTP to Resend. Fewer delivery headaches.
- Klaviyo plugged in clean on the Next.js frontends. Tags make life easy.
Thinking about spicing up your storefront with real-time video demos or live shopping sessions? Before you dive in, take a minute to skim this detailed ImLive review — it breaks down how a high-traffic cam platform handles streaming performance, user engagement, and friction-free payments, offering actionable lessons you can borrow when building similar live-commerce features in Node.
Likewise, if your catalog dips into adult or high-risk inventory, ad networks and classifieds can flip their policies overnight. The coverage of the AdultLook ban fallout shows exactly how fast a single platform change can nuke a traffic source — the piece maps the timeline, the impact on sellers, and concrete strategies for diversifying marketing so your Node checkout doesn’t stall when rules shift.
Hosting and Cost (Yes, It Matters)
- Vercel was perfect for frontends. Build previews saved my butt during design changes.
- Backends: Railway was easy for quick spins. Fly.io or DigitalOcean for control. PM2 + Nginx still works.
- Database: Supabase for Postgres with backups. Redis on Upstash for queues and cache.
Rough monthly for the band store: about $90–$130 across Vercel, Railway, Supabase, and Upstash. Spikes on big drops, but not scary.
Things I Wish Someone Told Me
- Use a queue (BullMQ) for emails, webhooks, and inventory sync. Your checkout will thank you.
- Cache product pages. I used stale-while-revalidate in Next.js. Inventory stayed fresh with a webhook poke.
- Rate limit checkout and cart. Bots will find you.
- Test coupons and taxes like a maniac. TaxJar made it sane for US. EU VAT took longer. Label your test orders clearly.
So… Which Path Should You Take?
- New store, simple rules, fast launch: Medusa + Next.js + Stripe. You’ll ship, then polish.
- Complex pricing or B2B flow: Vendure. It’s strict, but it won’t crumble.
- Weird logic or local quirks: Custom Express. Keep scope tight. Write tests.
If you’re a solo dev, stick with Medusa first. If you’re a small team with TypeScript chops, Vendure feels solid. If you’re a tinkerer with a strong coffee habit, custom is fun—but be real about maintenance.
My Verdict
Node.js e-commerce can be smooth, human, and fast. It lets you fix the tiny things that make a store feel right—like a gentle checkout or a tidy receipt. But it’s not magic. You still need logs, queues, and a plan when a webhook sneezes.
Would I bet my next store on Node again? Yeah. With eyes open, a queue ready, and a sticky note that says: “Don’t touch prod on Fridays.”
You know what? That note has saved me more than once.
