Tracking Transactions in PoolMind: From Frontend Polling to Backend Reliability


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:
User submits a transaction from the frontend.
I immediately start polling the Stacks Explorer API from the browser using the transaction ID.
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:
Submit transaction – The frontend sends the transaction ID and metadata (function name, user ID, NAV at the time, fees, etc.) to the backend.
Queue job – The backend adds a job to a Bull.js queue.
Background polling – Every 30 seconds, the job polls the Stacks Explorer API to check transaction status.
Update DB – Once confirmed (success, failed, or unprofitable), the backend updates the database with the final state.
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.
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.