Backend engineer based in Enugu, Nigeria. Over the past months at HNG and beyond, I shipped a profile management API with GitHub OAuth and NLP search, a distributed retry engine, and contributed to SkillBridge, a talent assessment platform built in NestJS. I care about systems that are honest, operable, and built to last.
Full-stack profile management system with GitHub OAuth 2.0 + PKCE, natural language search, role-based access control, and a matching CLI tool.
Node.js · Express · PostgreSQL · Redis · JWT
My work: Architected and built the entire backend from scratch: designed the PostgreSQL schema for profiles and users, implemented GitHub OAuth 2.0 with PKCE (S256 challenge) for both web and CLI clients with HTTP-only cookie transport and Authorization header support respectively. Built role-based access control (admin/analyst separation), a rule-based NLP query parser that converts plain English like 'adult males from Kenya' into parameterised SQL by resolving country names via REST Countries API to ISO codes and mapping age keywords to numeric ranges. Added API versioning middleware (X-API-Version header enforcement), Redis-backed rate limiting (auth: 10/min, API: 60/min with IPv6 subnet grouping), token blacklisting on logout/refresh, transparent token auto-refresh for both web and CLI, admin CSV export, profile aggregation dashboard, and the full CLI tool with device-code auth flow. Integrated Genderize.io, Agify.io, and Nationalize.io for name classification.
Background retry service that handles failed HTTP requests with exponential backoff, jitter, dead-letter queuing, and full attempt history.
Node.js · Express · SQLite
My work: Implemented the full system from a given spec: a 500ms-interval polling worker that queries SQLite for pending/retrying jobs whose nextRetryAt has elapsed, executes the HTTP request, and routes the result based on status code. 2xx marks completed, 4xx marks permanently failed (no retry), 5xx triggers exponential backoff (backoffMs * 2^attempt * jitter where jitter is 0.8-1.2 per attempt to prevent thundering herd). When attemptCount exceeds configurable maxRetries (default 5), the job moves to failed status as a dead-letter. Every attempt is recorded in a separate attempts table with status and message for full auditability. Built the REST API: POST /request for job submission with URL/method/body validation, GET /requests/:id with joined attempt history, and GET /requests?status= for filtering. All DB mutations use SQLite transactions for atomicity.
Backend for an AI-powered talent assessment and employer-candidate matching platform, built collaboratively during HNG Stage 8.
NestJS · TypeScript · PostgreSQL · TypeORM · Swagger
My work: Resolved AI-hallucinated broken resource URLs by building a UrlResolutionService that validates links via YouTube Data API v3 and Serper.dev Google Search, replacing fabricated URLs the LLM was generating. Built the full employer verification and trust layer: schema design, SSRF-hardened website reachability checks, LinkedIn validation, verification gates blocking unverified employers from sending offers or contacting candidates, hire-complete flow, and public employer profiles. Fixed skill assessment retake blocking, corrected question count mismatches across skill and advanced assessments, added configurable timeouts to all AI calls with background cache warming, served general learning resources pre-assessment, standardized all API responses to snake_case, and converted skill assessments to MCQ-only scoring. 23+ merged PRs total.
A background job scheduler with priority queuing, retries, dead-letter handling, and a live React dashboard for the Dilamme R&D Stage 9 challenge.
Node.js · SQLite · React · Vite
My work: Built a scheduler that creates, queues, processes, and tracks jobs while workers run independently in the background. Added retry handling with a maximum of 3 attempts, dead-letter queue recovery, priority ordering, cancellation handling, DAG workflow support, starvation prevention, and a live React dashboard to inspect queue state.
Insighta Deep Dive
Managing a growing set of user profiles sourced from external data providers (Genderize, Agify, Nationalize, REST Countries) and making them searchable without forcing users into rigid query syntax.
Express.js → PostgreSQL + Redis → External APIs. Clients (Web Portal + CLI) pass through CORS, JWT auth, and API versioning middleware before hitting routes. Redis handles sessions and token blacklisting. PostgreSQL stores profiles, users, and attempt history.
CLI OAuth exchange. Click to visit live deployment or query path directly.
Token rotation + blacklist. Click to visit live deployment or query path directly.
Natural language query. Click to visit live deployment or query path directly.
Natural language search without AI. I built a rule-based parser that maps plain-text phrases like "female adults from Nigeria under 30" to parameterised SQL conditions, resolving country names through the REST Countries API to ISO 3166 codes, and mapping age keywords to numeric ranges. No LLMs, no external NLP service.
Early in HNG I'd jump straight to implementation. By the third iteration of the Insighta Profiles API I had the schema, request flow, caching strategy, and rate limiting designed upfront. That shift made the code cleaner and debugging far less painful.
Before Insighta I would jump straight to code. Building the Profiles API for 2 million users forced me to think about schema design, request flow, caching strategy, and rate limiting before writing a single route. That upfront design work made the implementation faster and the system far more maintainable. I now treat architecture as part of the build, not a separate step.
Building the retry engine made me understand thundering herd problems in practice. Doubling the delay per retry is obvious, but rolling fresh jitter per attempt, not once, is the subtlety I would have missed without working through it hands-on.
Implementing GitHub OAuth with PKCE, HTTP-only cookies, Redis token blacklisting, and auto-refresh across both a web portal and a CLI taught me how many failure modes auth has. I think about session security very differently now.
Contributing 30+ PRs to SkillBridge with other developers taught me how to write code that others can review and maintain: consistent naming conventions, clear PR descriptions, proper test coverage, and thinking about how my changes affect the rest of the system. I also learnt the importance of API contracts and how creating them enforces good API design practices and conventions.
Open to backend engineering roles and collaborations. Enugu, Nigeria · UTC+1.