Full Stack · SaaS

Tracky — Multi-Tenant Issue Management System

Organization-wide bug tracking with eight role-specific portals and real-time updates

Tracky — Multi-Tenant Issue Management System — Overview

Overview1 / 9

Challenge

Serve eight very different user roles across isolated organizations on one platform — without data leaking between tenants and without polling for updates.

Solution

Designed a shared-database, tenant-isolated data model with layered route, controller, and service guards; in-memory access tokens with rotating HttpOnly refresh cookies and CSRF protection; and a WebSocket layer that selectively dispatches events only to the relevant actors.

Outcome

A production-grade issue platform covering the complete lifecycle — guest and partner intake, QA review, dev assignment, verification, and audit history — with instant cross-portal updates and one-command Docker deployment.

Architecture

Hover or tap a component to see what it does.

8 role portals: One app, eight dashboards — each role sees only its own lists, boards, analytics and actions.

Key decisions

One shared database for all tenants?

Simpler to run and migrate than a database per tenant. Every query is scoped by tenant ID, and suspended tenants are blocked at auth.

Access token in memory, not localStorage?

Nothing for an XSS attack to steal. A rotating HttpOnly refresh cookie restores the session on reload.

WebSockets instead of polling?

Comments and status changes should appear instantly. Events go only to the people on that issue, not everyone.

How is AI spend kept bounded?

Summaries auto-load for every stakeholder, so calls are cached, de-duplicated, quota-limited per user and tenant, and concurrency-capped.

Results

  • Full lifecycle, from report to QA-verified closure
  • 8 role dashboards on one codebase
  • Live updates across portals — no polling
  • AI summaries with capped spend
Read the detailed study

Overview

Tracky is a full-stack, multi-tenant issue and bug management platform. The Next.js frontend serves a tailored dashboard to each of eight roles — super admin, tenant admin, QA admin and member, dev admin and member, stakeholder, and point-of-contact employee — with issue lists, Kanban boards, rich issue detail pages, analytics with Excel export, and a public guest report form protected by email OTP verification.

The Express + Prisma + PostgreSQL backend enforces tenant isolation and role-based access on every route, runs the complete issue lifecycle from intake report to QA-verified closure with an event timeline, and pushes live notifications, comments and typing indicators over WebSockets. External systems submit reports through project-scoped API keys, and the whole stack runs with one docker compose command.

The problem

Eight very different user roles, across many isolated organizations, on one platform. A QA member, a developer and an outside stakeholder all need to see the same issue — but with different permissions, actions and views. Data from one organization must never appear in another.

Updates also had to feel instant. Polling eight kinds of dashboards for changes is wasteful and still feels slow.

Issue lifecycle

Issues don't go straight onto the board. Everything — from a portal user, a guest, or a partner system — first lands as a pending report in the project's QA queue. A QA reviewer accepts or rejects it; accepted reports become issues. Devs move them through assigned → in progress → fixed, and QA verifies the fix before the issue is resolved and closed. Issues can also be closed as 'not an issue'. Every change is written to an event timeline with its actor.

Tenant isolation

Tracky uses a shared-database model: tenant-owned tables (projects, issues, comments, events, notifications, API keys) carry a tenant ID and are indexed on it. Project codes are unique per tenant, not globally, so two organizations can both have a 'BUG' project.

Isolation is enforced in more than one place: role guards on routes, an auth middleware that rejects users of suspended tenants on every request, and services that scope every query by the tenant ID from the verified token — never from the request body.

Security pipeline and authentication

Every request passes Helmet security headers, CORS origin checks, a per-request ID for traceable logs, rate limiting (200 requests per 15 minutes in production), a 1MB body limit, recursive input sanitization, HTTPS enforcement in production, and CSRF validation on state-changing requests.

Login returns a short-lived access token that the frontend keeps only in memory (a Zustand store, not localStorage), plus two cookies: an HttpOnly refresh token and a readable CSRF token. Refresh tokens are stored hashed, rotated on every refresh, and revoked on logout. On page reload the app silently exchanges the cookie for a new access token.

Real-time layer

Clients connect to the WebSocket server with their access token, which is verified on the handshake. The server maps each user to a set of open sockets, so one person with several tabs gets every update in each. Instead of broadcasting, events are dispatched only to the actors on an issue — the creator, assigned devs, and that tenant's admins.

AI insights with bounded spend

Stakeholders get an AI executive summary on their landing page and can ask questions about their issue data, powered by DeepSeek. The model never sees raw issues: the backend aggregates up to 5,000 issues and 2,000 reports into a compact digest (capped at 14,000 characters), which also keeps prompts small and predictable.

Because the summary loads automatically, 30 stakeholders refreshing would mean 30 paid calls a minute. Four guards prevent that: a TTL cache so identical questions are free, single-flight so concurrent identical requests share one upstream call, per-user and per-tenant daily quotas, and a process-wide concurrency cap. Quota is only charged on a genuine cache miss.

Intake channels

Reports enter from three places: signed-in users inside a portal, guests through a public form verified by email OTP, and partner systems through the Partner API. Partner API keys are issued by a tenant admin, shown only once, stored as a hash, tied to a single tenant and project (so partners never send IDs), and can be revoked at any time.

Explore More Projects & Systems

All Projects →

01 / AI Security

Agent Monitor — Local Security Boundary for AI Agents & MCP

Architected a local-first security firewall and real-time activity monitor for autonomous AI agents and MCP tools, enforcing deterministic policy gating, capability sandboxing, and real-time execution telemetry.

02 / AI

Lumen — AI Marketing OS & Agent Suite

Built an integrated AI marketing platform combining a dynamic context chat agent (`aiagent`) with a full-featured Marketing Operating System SaaS (`marketingtool`) featuring multi-LLM routing, generative UI, Cloudinary asset pipelines, landing page builders, and automated lead capture.

03 / Full Stack

Headless E-commerce & Admin Infrastructure

Architected and developed a full-stack e-commerce system from scratch for a Swedish client, featuring a Next.js storefront backed by a custom Java Spring Boot REST API & MySQL CMS, cutting content management overhead by 40%.