HomeProjectsCertificationsBlogAboutContact

A Legacy of Building & Scaling

Showcasing 6+ years of architecting high-performance systems and AI-driven solutions.

Aug 2021 - Present

Senior Software Engineer

Vivid Technologies • Full-Time
Lahore, Pakistan (Remote)

I have spent the last five years as a senior backend engineer leading architecture for 15+ production applications. The user base totals over 150,000 across clients in Europe, North America, Oceania, and Asia. This post covers what I built, what broke, and the patterns that survived.

The Portfolio at a Glance

Every app in the portfolio runs on a consistent core stack: Laravel or Node.js on the backend, Vue.js, Quasar, or React on the frontend, MySQL or PostgreSQL for persistence, Redis for caching and queues, and AWS with S3 for storage and infrastructure. Consistency at the stack level cuts onboarding time in half when a new engineer joins a project.

The scale ranges across client types. Some are high-traffic consumer platforms. Others are niche B2B tools with 50 daily users but strict compliance demands. Both categories teach different lessons.

A Multilingual News Platform: Scaling Content Across 17 Languages

One of the flagship projects is a multilingual news platform covering 17 languages with domain mapping, per-locale sitemaps, RSS syndication, and permalink logic that handles edge cases CMS cores do not.

Three things I learned maintaining it:

Domain mapping is fragile without guardrails. Regex-based redirects work until a translator adds a slug with a diacritic the CMS silently re-encodes. I wrote validation into the deployment pipeline to catch broken permalinks before they hit production.

Sitemaps are an SEO contract. For a news site, a late sitemap means missing the Google News indexing window. I moved sitemap regeneration to a queued job with a 5-minute SLA and alerting on failure.

RSS enclosures matter more than people think. Aggregators drop feeds with malformed enclosures. A single bad image MIME type cost a partner syndication placement. Defensive parsing is cheaper than recovering lost distribution.

A Social Collaboration Platform: 150,000 Users and Counting

One project in the portfolio handles social collaboration features for a user base in six figures. The interesting engineering problems sit in the notification layer and the feed assembly pipeline, not the CRUD.

Redis saved this project multiple times. Feed assembly for active users runs off cached aggregates refreshed on write. The write-amplification cost is real, but it is cheaper than rebuilding a feed from MySQL on every pull at scale.

Laravel Horizon for queue monitoring is non-negotiable above ~50k users. When a third-party push notification provider started silently dropping jobs, Horizon’s failure dashboard surfaced the pattern within an hour.

The Other 13 Apps: Patterns That Scale

The rest of the portfolio covers coaching platforms, health and fitness apps, cooperative time-credit systems, trading platforms with charting integrations, and booking engines. Three patterns survived across all of them:

One: Forge plus GitLab CI/CD is the default. Every project uses the same deploy script structure. Changing infrastructure tooling per-client is a tax nobody pays you for.

Two: Database design decisions compound. A client platform I inherited had 30 nullable columns on a core users table. Two years of feature growth turned that into a migration nightmare. I now refuse to add a nullable column without a written reason in the migration comment.

Three: Webhook reliability is a product feature. Clients across multiple regions integrate with local payment processors, CRMs, and compliance tools. Every outbound webhook goes through a retry queue with exponential backoff and a dead-letter inspection UI. Clients notice when integrations do not silently fail.

S3 and AWS Patterns That Paid Off

A few infrastructure decisions repeated across projects earned their keep:

  • S3 presigned URLs for user uploads — keeps the application server out of the upload path and cuts bandwidth costs at scale
  • CloudFront in front of S3 for media-heavy apps, configured with signed cookies for private content
  • Separate buckets for user content, system backups, and transient processing artifacts — makes lifecycle policies and cost attribution clean
  • Queued image transformations using Node.js workers pulling from Redis, writing derivatives back to S3

The separation of concerns between Laravel handling business logic and Node.js handling stream-heavy or real-time work showed up repeatedly. Neither replaces the other. Using both correctly is the point.

What Leading the Backend Actually Means

Writing backend code is maybe 40% of the job now. The rest splits across:

  • Architecture reviews for new features, where the goal is catching bad data models before they ship
  • Mentoring junior developers on ORM patterns, queue design, and why N+1 queries kill production
  • Client technical conversations — translating “the site feels slow” into a concrete profiling task
  • Infrastructure decisions — when managed cloud wins, when bare-metal VPS wins, and when a CDN load balancer is worth the complexity

The code skills got me the senior title. The communication skills kept me there.

Nov 2019 - Aug 2021

Full Stack Developer

Maqware Solutions • Full-Time
Lahore, Pakistan (On-Site)

Before leading backend architecture for a production portfolio, I spent two years as a full stack developer building business platforms across wildly different domains. Supply chain with integrated telephony. Insurance workflows. CRMs. Real-time chat. Ticket management. Same core stack, very different problem shapes. This post covers what I learned shipping across verticals.

The Stack That Carried Every Project

The core stack stayed consistent: Laravel on the backend, Vue.js for interactive frontends, and Node.js for anything real-time or stream-heavy. MySQL for the relational core, Redis for caching and queues, and third-party APIs for the vertical-specific pieces.

Working across verticals teaches you what the stack is good at and where it bends. Laravel handles business logic, authentication, and domain models cleanly. Vue.js keeps frontends interactive without the framework fatigue. Node.js picks up the slack for WebSockets, event streams, and anything that does not fit a request-response model.

Supply Chain with Twilio Voice Integration

The supply chain platform was the most technically layered project. Orders flowed through multiple vendor statuses, but the interesting engineering sat in the telephony layer. Twilio powered inbound and outbound calling directly from the dashboard, with call routing based on order status, agent availability, and customer priority.

Three lessons from that build:

Webhooks are a distributed system. Twilio status callbacks arrive out of order. Treating every webhook as an idempotent event with a status machine on your side is the only way to avoid duplicate call logs and missed disconnections.

Voice data is expensive to store carelessly. Call recordings hit disk fast. S3 with lifecycle policies that archive older recordings to Glacier kept storage costs predictable.

Real-time UI needs a queue between the event and the browser. Pushing Twilio events directly to a Laravel broadcast channel works until volume spikes. Buffering through Redis with a Node.js worker publishing to sockets keeps the frontend responsive under load.

Insurance Workflow Platform

Insurance taught me that data modeling decisions are the whole game. Policies, claims, beneficiaries, and document attachments all have legal definitions that do not bend to convenient schemas.

The instinct to normalize aggressively has to be weighed against audit requirements. When a claim needs to be reconstructable exactly as it looked on the filing date, denormalized snapshots stored at submission time are not duplication — they are compliance. I learned to ask “who needs to read this data in five years?” before finalizing a migration.

Form-heavy frontends also shaped how I use Vue.js. Deeply nested forms with conditional validation rules benefit from composables that centralize logic. Component-local state scatters validation across the tree and becomes unmaintainable by the second revision.

CRM Platform: Pipeline Management at Agency Scale

The CRM served multiple agency workflows — lead capture, pipeline stages, activity tracking, and email sync. The hard part was not features. It was permissions.

Multi-tenant role-based access control is easy to underestimate. Every endpoint, every query, every report needs to respect organization boundaries. I leaned on Laravel policies and global scopes to enforce tenancy at the query level rather than the controller level. Filtering at the query layer means a missed authorization check in a controller cannot leak data across tenants.

Real-Time Chat and Ticket Management

The chat and ticketing projects overlapped in engineering problems even though they served different use cases. Both needed:

  • Presence tracking — who is online, who is typing, who last viewed the thread
  • Message delivery guarantees — at-least-once with client-side deduplication
  • Notification fan-out — web push, email digest for offline users, and in-app badges
  • Attachment handling — with virus scanning before files hit permanent storage

Node.js with Socket.IO handled the real-time transport. Laravel owned the persistence and business rules. The split worked because the responsibilities were clean: Node.js never touched the database directly, Laravel never managed socket state.

Patterns That Moved with Me to the Next Role

A few habits formed during this stretch that I still use daily:

Queue everything that does not need to be synchronous. Email, webhook dispatching, report generation, notification fan-out — all queued. A synchronous email send blocks the request for the benefit of nobody.

Write seeders for production-realistic data. Demo seeders with 10 rows hide scaling problems. Seeders that generate 50,000 realistic records surface slow queries before the client’s first real import does.

Favor Eloquent relationships over raw joins until the query actually needs raw SQL. Readability compounds across a team. Premature raw SQL optimization makes the codebase hostile to the next developer.

Write migrations as if the database survives the codebase. Column comments, explicit foreign keys, and named indexes cost nothing to add and save hours when someone three years from now tries to understand the schema.

Sep 2018 - Nov 2019

Software Engineer

Vizrex Private Limited • Full-Time
Lahore, Pakistan (On-Site)

My First Year as a Software Engineer: Lessons from Shipping PHP and Laravel Projects in Production

Every backend engineer remembers their first production deploy. Mine came during my first software engineering role, fresh out of GC University Lahore with a BSCS degree and an ICT R&D scholarship behind me. I joined as a software engineer working across a mix of web projects in PHP, Laravel, and jQuery. This post covers the foundational habits that role built — the ones I still use seven years later.

The Stack That Defined My Foundation

The work spanned PHP for legacy maintenance, Laravel for new builds, and jQuery for the interactive layer. MySQL handled persistence. Apache and Nginx served the apps. Git workflows were learned the hard way through real merge conflicts.

This stack is unfashionable to some now. It should not be. PHP and jQuery taught me more about HTTP, the request lifecycle, and DOM manipulation than any modern framework would have at that stage. The fundamentals stick because the abstractions are thinner.

What “A Mix of Web Projects” Actually Teaches You

The variety mattered more than the individual projects. In a single year I touched:

  • Custom CMS builds in raw PHP, where I learned why frameworks exist by feeling the absence of one
  • Laravel applications with Eloquent, Blade templating, and queue workers — my first exposure to MVC done right
  • Frontend work in jQuery with AJAX-driven interfaces, before SPAs became the default
  • Database design for relational schemas with foreign keys, indexes, and normalization decisions that had real consequences
  • Bug fixing on inherited codebases — possibly the most underrated skill development of any junior role

Bouncing across project types forces you to recognize patterns. By month six I could spot a poorly indexed query by reading the schema. By month nine I could refactor a tangled controller into something maintainable without breaking the existing tests.

The Three Habits That Stuck

Read the codebase before writing code. Inherited projects taught me that ten minutes of reading saves two hours of debugging. The temptation to start typing immediately is a junior trap. I still open every new project with grep and a directory listing before I touch anything.

Test queries with realistic data. A query that returns 50 rows in development can return 50,000 in production. I learned this the embarrassing way when a report timed out for a real client. Now every query gets pressure-tested with seeded data that approximates production volume.

Write code as if the next maintainer is angry and knows where you live. Comments on non-obvious decisions. Variable names that explain intent. Avoiding clever one-liners that take ten minutes to decode. The next maintainer is usually you, six months later, with no memory of why you wrote it that way.

Working with PHP Before the Modern Tooling

Modern PHP development with Composer, PHP 8 features, and proper static analysis tools is a different sport than what I started with. Working without those luxuries built useful instincts:

  • Manual dependency tracking made me appreciate Composer when I finally adopted it
  • No type hints meant runtime debugging was constant — which sharpened reading skills
  • Procedural PHP scripts taught me where OOP actually earns its complexity and where it does not

Engineers who started with Laravel and never wrote raw PHP sometimes miss the layer underneath. Knowing what the framework is doing for you is what lets you debug it when it breaks.

Laravel as a First Framework

Picking up Laravel during this role shaped how I think about backend code to this day. Eloquent’s expressive query syntax, Blade’s clean templating, and the artisan command structure made the framework feel cohesive rather than bolted together.

Three Laravel concepts I internalized in this role and never let go of:

  • Service providers and the container — understanding dependency injection at a framework level translates to every modern stack
  • Middleware as request lifecycle hooks — a mental model that maps cleanly to Express, Fastify, and most other backend frameworks
  • Queues and jobs — even simple email-sending taught me to think about what work belongs in the request and what belongs in the background

These concepts were not unique to Laravel, but Laravel was where I learned them clearly.

What a Junior Role Is Actually For

The output of the first year was not the projects I shipped. It was the engineering instincts I built. Code review feedback, production incidents, client-facing demos that did not go to plan, and the slow accumulation of pattern recognition — that is what a first role provides.

Engineers looking to skip the foundational years for the senior title later usually pay for it in gaps that are hard to fill. The grind of debugging legacy PHP at 11 PM is what makes the architecture decisions at 11 AM five years later look easy.

What Came Next

After Vizrex I moved to a full stack developer role building supply chain platforms with Twilio integration, insurance workflows, CRMs, and real-time chat. Then to a senior backend engineer position leading architecture for 15+ production applications serving 150,000+ users across international clients.

None of that would have been possible without the unglamorous first-year work — reading other people’s PHP, debugging jQuery event handlers, and learning what production actually looks like.

Ready to start your next project?

Let's combine my experience with your vision to build something extraordinary.

Get in Touch