Tracking Transactions in PoolMind: From Frontend Polling to Backend Reliability

David JohnDavid John
3 min read

Introduction

When I first built PoolMind, one of my big questions was: how do we know whether a blockchain transaction actually succeeded?
On Stacks, a transaction can be pending, succeed, fail, or even succeed but still be unprofitable (because of fees eating into NAV). Tracking this correctly isn’t just a nice-to-have — it powers user dashboards, analytics, and ensures fees + NAV are calculated right.


Naive Approach: Frontend Polling

My first attempt was simple:

  1. User submits a transaction from the frontend.

  2. I immediately start polling the Stacks Explorer API from the browser using the transaction ID.

  3. Once the status was known, I stored it in the database.

This worked… until it didn’t.

  • If the user closed the tab or reloaded the page, tracking stopped.

  • Transactions could go unrecorded.

  • It wasn’t reliable enough for something as important as user balances.


Backend-Driven Solution: Bull.js Queues

The fix was obvious: don’t trust the frontend with mission-critical tracking.

Here’s how we rebuilt it:

  1. Submit transaction – The frontend sends the transaction ID and metadata (function name, user ID, NAV at the time, fees, etc.) to the backend.

  2. Queue job – The backend adds a job to a Bull.js queue.

  3. Background polling – Every 30 seconds, the job polls the Stacks Explorer API to check transaction status.

  4. Update DB – Once confirmed (success, failed, or unprofitable), the backend updates the database with the final state.

  5. Frontend pulls from backend – Instead of querying the blockchain directly, the frontend just asks the backend for transaction status.


Transaction States We Track

We care about 4 main states:

  • Pending → Transaction is broadcast but not yet confirmed.

  • Success → Confirmed in a block and profitable.

  • Failed → Transaction aborted or rejected.

  • Unprofitable → Technically succeeded, but fees or NAV made the outcome negative.

This gives us a much richer picture than just “success” or “fail.”


Database Model (Simplified)

transactions (
  id SERIAL PRIMARY KEY,
  user_id UUID,
  tx_id TEXT UNIQUE,
  function_name TEXT,
  nav_at_tx NUMERIC,
  fee NUMERIC,
  status TEXT CHECK (status IN ('pending','success','failed','unprofitable')),
  created_at TIMESTAMP DEFAULT NOW()
);

System Flow Diagram

Old Way (Frontend Polling)

User → Frontend → Explorer API → (maybe DB)

New Way (Backend Queues)

User → Frontend → Backend → Bull.js Queue → Explorer API → Database → Frontend

Lessons Learned

  • Don’t trust the frontend with transaction tracking. Users close tabs.

  • Background jobs (Bull.js) give reliability and retry logic.

  • Tracking extra metadata (fees, NAV, function name) turns raw blockchain data into useful UX.

  • Next step: build better failure handling + notification when a transaction fails.


🚀 This evolution shows how PoolMind goes beyond toy dApps into production-ready blockchain UX.

0
Subscribe to my newsletter

Read articles from David John directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

David John
David John

Professional Biography: In the technology realm, others see code. I see art. My journey as a software engineer is fueled by a steadfast conviction in the power of creativity to transform our world and the ability of technology to unleash human potential. As a self-taught developer from Nigeria, I have taken a unique route fueled by a constant inquiry and an insatiable thirst for invention. I spent my five years as a developer growing from a lone learner to a versatile full-stack developer and enthusiast for artificial intelligence. Today, my technological landscape spans web development, artificial intelligence, and blockchain technologies, each established through learning about multiple frameworks. Technical Skills: In terms of technical skills, I possess a broad breadth and depth. I know multiple programming languages - Python, JavaScript, Ruby, and C - and possess exceptional knowledge of multiple web technologies - React, Next.js, Node.js, Django, and upcoming frameworks. When I approach code development, I don't just think of it as code. I think of it as compositions. Each line of code is like a musical note bringing functionality together to create a symphony. Professional Philosophy: More than skills, I have a vision to create opportunities. Having seen dauntless ambition and unmet creativity in uninviting environments, I believe technology has the possibility of leveling the playing field. I find coding far more relevant than code; to me, it's about giving people a chance to unearth their expression and potential. Current Frontiers: I'm currently digging deep into the intersections of AI, web development and blockchain technologies. My excitement surrounding cryptocurrencies and programmable assets stems from a mindset I have toward a more fluid, easier to access digital ecosystem. I view these technologies as tools for innovation rather than things that are far off in the future.