<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Kelechukwu Amadi-Keke</title>
    <description>The latest articles on DEV Community by Kelechukwu Amadi-Keke (@nulfacedesigner).</description>
    <link>https://dev.to/nulfacedesigner</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3509198%2F9c540263-8efd-4a10-88ed-c3bd9ba45ac8.png</url>
      <title>DEV Community: Kelechukwu Amadi-Keke</title>
      <link>https://dev.to/nulfacedesigner</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nulfacedesigner"/>
    <language>en</language>
    <item>
      <title>I Built My Own Analytics Platform Instead of Paying for PostHog</title>
      <dc:creator>Kelechukwu Amadi-Keke</dc:creator>
      <pubDate>Sun, 07 Jun 2026 23:00:00 +0000</pubDate>
      <link>https://dev.to/nulfacedesigner/i-built-my-own-analytics-platform-instead-of-paying-for-posthog-5fkn</link>
      <guid>https://dev.to/nulfacedesigner/i-built-my-own-analytics-platform-instead-of-paying-for-posthog-5fkn</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Let me clear one thing up right out of the gate: this is not a teardown of PostHog. In fact, PostHog is an incredible piece of software and one of the primary inspirations for my journey.&lt;/p&gt;

&lt;p&gt;But while grinding away on my own side projects, I kept hitting the exact same wall. I desperately wanted product analytics, system monitoring, and operational visibility, but I didn't want the cognitive overhead of managing four different platforms. I didn't want to copy-paste half a dozen different tracking scripts into my frontend, and I definitely didn't want another stack of recurring monthly SaaS bills.&lt;/p&gt;

&lt;p&gt;So, like any developer facing a minor inconvenience, I decided to spend weeks of my life building my own solution from scratch.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Stack of Disconnected Tools
&lt;/h2&gt;

&lt;p&gt;Most indie hackers and small dev teams follow a very predictable path when it comes to keeping tabs on their apps:&lt;/p&gt;

&lt;p&gt;-They launch with zero observability because they just want to ship.&lt;/p&gt;

&lt;p&gt;-They realize they have no idea if anyone is visiting, so they drop in an analytics script.&lt;/p&gt;

&lt;p&gt;-Users start complaining about silent crashes, so they sign up for an error-tracking tool.&lt;/p&gt;

&lt;p&gt;-The server drops offline while they're asleep, so they set up an uptime ping tool.&lt;/p&gt;

&lt;p&gt;-They notice their database queries are lagging, so they look for an API monitoring solution.&lt;/p&gt;

&lt;p&gt;Before you know it, your lean side project is held together by duct tape and a collection of disconnected, expensive browser tabs. Each tool solves its individual problem perfectly, but collectively, they introduce massive friction. You find yourself jumping between dashboards just to answer a basic question like, "Did that spike in traffic cause my API response times to degrade?"&lt;/p&gt;

&lt;p&gt;I didn't want a suite of tools. I wanted a single, unified lens.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Blueprint for observe
&lt;/h2&gt;

&lt;p&gt;My checklist was simple. I wanted four distinct capabilities living under the exact same roof, visible on a single glass pane:&lt;/p&gt;

&lt;p&gt;-Product Analytics: Understanding user behavior and feature adoption.&lt;/p&gt;

&lt;p&gt;-Uptime Monitoring: Knowing the exact minute my servers take a hit.&lt;/p&gt;

&lt;p&gt;-Error Tracking: Snagging stack traces before the user bounces.&lt;/p&gt;

&lt;p&gt;-API Metrics: Keeping an eye on endpoint latencies and failure rates.&lt;/p&gt;

&lt;p&gt;To make this happen without overcomplicating my life, I leaned on a battle-tested, high-performance stack: React on the frontend, FastAPI for the heavy-lifting API gateway, PostgreSQL as the reliable data anchor, and Redis + Celery to handle the asynchronous background queues.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Hardest Part Wasn't the Tech
&lt;/h2&gt;

&lt;p&gt;Going into this, I assumed the technical hurdles would be the bottleneck. I figured I'd lose sleep over authentication flows, Docker deployments, or wiring up responsive charts.&lt;/p&gt;

&lt;p&gt;It turned out those were the easy parts. The real headache, was data modeling and identity resolution.&lt;/p&gt;

&lt;p&gt;When you build an analytics engine, you are forced to ask incredibly precise philosophical questions about your data:&lt;/p&gt;

&lt;p&gt;-Who exactly is a visitor versus a registered user?&lt;/p&gt;

&lt;p&gt;-How do you seamlessly stitch together an anonymous session from a phone with an identified user profile on a desktop three days later without duplicating data?&lt;/p&gt;

&lt;p&gt;-If an API endpoint fails, how do you contextually link that specific error to the exact user journey that triggered it?&lt;/p&gt;

&lt;p&gt;Figuring out how to link these disparate event streams into a cohesive story was a masterclass in database design. I quickly realized that observability isn't a data collection problem—anyone can dump JSON into a database. It’s a data synthesis problem. The value isn't in storing the events; it's in making those events mean something to a tired developer at 2:00 AM.&lt;/p&gt;

&lt;p&gt;Final Thoughts: Should You Build Your Own?&lt;/p&gt;

&lt;p&gt;If you are running a fast-growing startup or trying to get a commercial product off the ground, my honest advice is: probably not. Use PostHog, use Plausible, use Sentry. Your time is better spent building your actual core product. Or, if you are an indie dev like me with a small budget? Use &lt;a href="https://useobserve.xyz" rel="noopener noreferrer"&gt;Observe.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But I didn't build observe because I thought the market was lacking another dashboard. I built it because I wanted to tear down the black box. I wanted to deeply understand the engineering behind high-throughput data ingestion, and I wanted a tool custom-tailored to how I think and work.&lt;/p&gt;

&lt;p&gt;No matter what happens to the project next, the sheer amount of architectural grit I gained from building an analytics pipeline from scratch was worth every single line of code.&lt;/p&gt;

</description>
      <category>development</category>
      <category>monitoring</category>
      <category>api</category>
      <category>analytics</category>
    </item>
    <item>
      <title>Building a PostHog-Like Analytics Platform with FastAPI</title>
      <dc:creator>Kelechukwu Amadi-Keke</dc:creator>
      <pubDate>Fri, 05 Jun 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/nulfacedesigner/building-a-posthog-like-analytics-platform-with-fastapi-10dd</link>
      <guid>https://dev.to/nulfacedesigner/building-a-posthog-like-analytics-platform-with-fastapi-10dd</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;At a high level, analytics platforms seem deceptively simple. A user clicks a button, an event payload hits an endpoint, and a pretty dashboard displays the result.&lt;/p&gt;

&lt;p&gt;But the moment you sit down to architect one yourself, you realize the rabbit hole goes incredibly deep. I recently built observe, an all-in-one analytics and observability platform, to solve my own dashboard fatigue. Moving from consuming analytics to building the actual pipeline forced me to rethink how data moves through a system.&lt;/p&gt;

&lt;p&gt;Here is a look under the hood at the architectural decisions, bottlenecks, and data modeling lessons behind building a telemetry platform from scratch.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Core Data Unit: The Event
&lt;/h2&gt;

&lt;p&gt;Everything in an analytics platform lives and dies by the event. A lightweight frontend SDK captures user activity in the browser and fires it off to an ingestion endpoint.&lt;/p&gt;

&lt;p&gt;A standard payload might look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;JSON&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"anonymous_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"usr_abc123"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"button_clicked"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"properties"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"element_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"signup_btn"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/pricing"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"screen_width"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1440&lt;/span&gt;&lt;span class="w"&gt;    
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Receiving this JSON is the easy part. The real engineering challenge lies in how you ingest, process, and query this data without locking up your database or making your dashboard crawl.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Identity Problem: Visitors vs. Users
&lt;/h2&gt;

&lt;p&gt;One of the first structural hurdles I ran into was mapping user identity. You have to explicitly design for two distinct states:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Visitor (Anonymous): Someone browsing your landing page before they’ve signed up.&lt;/li&gt;
&lt;li&gt;The User (Identified): A verified account with a specific ID in your database.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To build a cohesive user journey, your system has to track anonymous activity via local device IDs, store those events, and then dynamically alias or merge that history into the real user profile the exact moment they log in or sign up. If you don't model this relationship correctly from day one, your retention charts and user funnels will be completely broken.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Production Backend Stack
&lt;/h2&gt;

&lt;p&gt;To handle ingestion and processing without breaking the bank, I settled on a classic, robust asynchronous stack:&lt;/p&gt;

&lt;p&gt;-FastAPI: Acts as the high-throughput gateway. It takes incoming HTTP POST requests from the SDK, validates the schema instantly using Pydantic, and offloads the heavy lifting.&lt;/p&gt;

&lt;p&gt;-PostgreSQL: Serves as the source of truth for user accounts, session data, and core aggregates.&lt;/p&gt;

&lt;p&gt;-Redis: Acts as our ultra-fast caching layer and the message broker handling the system's internal communication.&lt;/p&gt;

&lt;p&gt;-Celery: The workhorse that processes event queues and runs background tasks out-of-band.&lt;/p&gt;

&lt;p&gt;[ Frontend SDK ] ---&amp;gt; ( FastAPI Ingestion ) ---&amp;gt; [ Redis Queue ] ---&amp;gt; [ Celery Workers ] ---&amp;gt; [ PostgreSQL ]&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Async Background Processing is Non-Negotiable
&lt;/h2&gt;

&lt;p&gt;When you’re first starting out, writing every incoming event directly to SQL works fine. But at scale, hitting your database on every single page click is architectural suicide; it immediately bottlenecks your API and degrades the end-user experience.&lt;/p&gt;

&lt;p&gt;By introducing Celery and Redis into the mix, the FastAPI ingestion endpoint does exactly one job: it validates the JSON format, drops the raw payload into a Redis queue, and immediately returns a 202 Accepted response to the client.&lt;/p&gt;

&lt;p&gt;This decoupling unlocks massive performance benefits:&lt;/p&gt;

&lt;p&gt;-Event Batching: Celery workers can pool events in memory and perform bulk database inserts (e.g., writing 500 events in a single SQL transaction instead of 500 individual writes).&lt;/p&gt;

&lt;p&gt;-Isolated Failure: If the database experiences a sudden spike or goes down for maintenance, the API keeps accepting events. The data sits safely in the Redis queue until the database recovers.&lt;/p&gt;

&lt;p&gt;-Heavy Lifting Separation: Background workers handle intensive cron jobs—like running periodic uptime pings, processing historical error rates, and calculating daily usage statistics—without stealing a single CPU cycle from the live API.&lt;/p&gt;

&lt;p&gt;Frontend: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5ha0ytgvjjgc8q27a53g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5ha0ytgvjjgc8q27a53g.png" alt="Logged Events"&gt;&lt;/a&gt;&lt;br&gt;
For the frontend, I used React paired with modern charting libraries to visualize event streams, error spikes, uptime history, and API response latencies.&lt;/p&gt;

&lt;p&gt;Going into this, I assumed the frontend would be the straightforward part. I was wrong. Building a chart is easy; designing a dashboard that helps people make decisions is incredibly difficult.&lt;/p&gt;

&lt;p&gt;When you have access to a massive pool of raw event data, the temptation is to graph everything. But endless rows of line charts quickly turn into cognitive noise. The real challenge was exercising restraint—filtering out the vanity metrics and structuring the UI so a developer can log in and see exactly what is broken within three seconds.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I learned
&lt;/h2&gt;

&lt;p&gt;Looking back at the development of observe, a few foundational rules stood out:&lt;/p&gt;

&lt;p&gt;-Observability is a data modeling problem: If your database schemas aren't optimized for time-series data or rapid aggregation, your app will choke as soon as you hit millions of rows.&lt;/p&gt;

&lt;p&gt;-Ingestion is easy; analysis is hard: Writing data into a system at high speed is a solved problem. Writing it in a way that allows a user to query complex funnels and cohorts in real-time is where the real engineering happens.&lt;/p&gt;

&lt;p&gt;-Simplicity is a premium feature: The ultimate goal isn't to build a tool with the most configuration toggles. It’s to build a tool that gives you the maximum amount of operational clarity with the absolute minimum amount of friction.&lt;/p&gt;

&lt;p&gt;Closing Thoughts&lt;/p&gt;

&lt;p&gt;Building an analytics engine from scratch completely changed how I view observability tools. What looks like a simple, smoothly updating line graph on your screen is almost always the tip of an iceberg—supported by millions of micro-decisions, background queues, and data pipelines running silently beneath the surface.&lt;/p&gt;

&lt;p&gt;Check out Observe: &lt;a href="https://useobserve.xyz" rel="noopener noreferrer"&gt;https://useobserve.xyz&lt;/a&gt;&lt;/p&gt;

</description>
      <category>analytics</category>
      <category>monitoring</category>
      <category>api</category>
      <category>development</category>
    </item>
    <item>
      <title>This is a submission for the GitHub Finish-Up-A-Thon Challenge</title>
      <dc:creator>Kelechukwu Amadi-Keke</dc:creator>
      <pubDate>Tue, 02 Jun 2026 09:46:02 +0000</pubDate>
      <link>https://dev.to/nulfacedesigner/this-is-a-submission-for-the-github-finish-up-a-thon-challenge-2664</link>
      <guid>https://dev.to/nulfacedesigner/this-is-a-submission-for-the-github-finish-up-a-thon-challenge-2664</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/github-2026-05-21"&gt;GitHub Finish-Up-A-Thon Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;Over the past few weeks, I built observe., an observability platform designed to help developers understand what is happening inside their applications. I built it because myself and some other Nigerian developers couldn't keep up with the cost of enterprise tools.&lt;/p&gt;

&lt;p&gt;The platform combines several capabilities that are often spread across multiple tools:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Product analytics&lt;/li&gt;
&lt;li&gt;Uptime monitoring&lt;/li&gt;
&lt;li&gt;Error tracking&lt;/li&gt;
&lt;li&gt;API monitoring&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal was simple: provide a single dashboard where developers can answer questions like:&lt;/p&gt;

&lt;p&gt;Are users actually using my product?&lt;br&gt;
Which features are being used?&lt;br&gt;
Is my application online?&lt;br&gt;
Are there increasing error rates?&lt;br&gt;
Are API endpoints slowing down?&lt;/p&gt;

&lt;p&gt;The project is built with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;FastAPI&lt;/li&gt;
&lt;li&gt;PostgreSQL&lt;/li&gt;
&lt;li&gt;Redis&lt;/li&gt;
&lt;li&gt;Celery&lt;/li&gt;
&lt;li&gt;React&lt;/li&gt;
&lt;li&gt;TypeScript&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What started as an exploration of analytics systems eventually grew into a complete end-to-end product with event ingestion, monitoring services, background workers, dashboards and project management.&lt;/p&gt;
&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;Live Project&lt;/p&gt;

&lt;p&gt;&lt;a href="https://useobserve.xyz" rel="noopener noreferrer"&gt;Observe.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Source Code&lt;br&gt;
Backend: &lt;a href="https://github.com/Im-Kaycee/Observability-backend" rel="noopener noreferrer"&gt;https://github.com/Im-Kaycee/Observability-backend&lt;/a&gt;&lt;br&gt;
Frontend: &lt;a href="https://github.com/Im-Kaycee/observability-dashboard" rel="noopener noreferrer"&gt;https://github.com/Im-Kaycee/observability-dashboard&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Screenshots&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0au4fpjjjsyxo0u6wzxp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0au4fpjjjsyxo0u6wzxp.png" alt="Dashboard" width="800" height="382"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fslsqjmrh5fmy5656pufr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fslsqjmrh5fmy5656pufr.png" alt="Events logged" width="799" height="381"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fze28r10hcq7gb5lbgyd9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fze28r10hcq7gb5lbgyd9.png" alt="Uptime monitoring" width="800" height="382"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ny1e19qu2ji2gkz3yso.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ny1e19qu2ji2gkz3yso.png" alt="Error monitoring" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Video Walkthrough&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/Ii2BUPewPhQ"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  The Comeback Story
&lt;/h2&gt;

&lt;p&gt;This project started as a much smaller analytics experiment.&lt;/p&gt;

&lt;p&gt;Initially, the focus was simply recording events from applications and displaying them in a dashboard.&lt;/p&gt;

&lt;p&gt;As development continued, I realized that analytics alone only tells part of the story.&lt;/p&gt;

&lt;p&gt;Knowing what users are doing is useful, but it doesn't tell you:&lt;/p&gt;

&lt;p&gt;When your application is down&lt;br&gt;
Whether APIs are healthy&lt;br&gt;
If users are encountering errors&lt;/p&gt;

&lt;p&gt;So I expanded the project into a broader observability platform.&lt;/p&gt;

&lt;p&gt;Some of the major additions included:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Event Ingestion Pipeline&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I built a system that accepts events from client applications and stores them for analysis.&lt;/p&gt;

&lt;p&gt;This required designing concepts such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Projects&lt;/li&gt;
&lt;li&gt;API keys&lt;/li&gt;
&lt;li&gt;Visitors&lt;/li&gt;
&lt;li&gt;Users&lt;/li&gt;
&lt;li&gt;Events&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;and understanding how modern analytics platforms associate anonymous activity with identified users.&lt;/p&gt;

&lt;p&gt;2.Monitoring Services&lt;/p&gt;

&lt;p&gt;I added uptime monitoring and API monitoring so developers can track application health alongside user behavior.&lt;/p&gt;

&lt;p&gt;Background Processing&lt;/p&gt;

&lt;p&gt;Using Celery and Redis, I introduced background workers for tasks that shouldn't run inside request-response cycles.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Dashboard Experience&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;One of the biggest improvements was the frontend.&lt;/p&gt;

&lt;p&gt;I redesigned the interface around a clean, serious aesthetic with subtle neobrutalist accents to make large amounts of monitoring data easier to navigate.&lt;/p&gt;

&lt;p&gt;By the end of the challenge, the project had evolved from a partially completed analytics idea into a fully functional observability platform.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Experience with GitHub Copilot
&lt;/h2&gt;

&lt;p&gt;GitHub Copilot helped accelerate development throughout the project.&lt;/p&gt;

&lt;p&gt;Some of the areas where it was most useful included:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Boilerplate Generation&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Copilot was particularly effective at generating repetitive code such as:&lt;/p&gt;

&lt;p&gt;CRUD endpoints&lt;br&gt;
Database models&lt;br&gt;
Schema definitions&lt;br&gt;
Validation logic&lt;br&gt;
Refactoring&lt;/p&gt;

&lt;p&gt;As the architecture evolved, Copilot helped quickly update code paths and maintain consistency across files.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Frontend Development&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Building dashboards often involves repetitive UI patterns. Copilot significantly reduced the time required to create and iterate on components.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Learning and Exploration&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;One of the most valuable aspects was using Copilot as a development companion while working through unfamiliar implementation details and architectural decisions.&lt;/p&gt;

&lt;p&gt;Rather than replacing problem solving, it allowed me to spend more time thinking about system design and product decisions instead of writing repetitive code.&lt;/p&gt;

&lt;p&gt;Built by&lt;/p&gt;

&lt;p&gt;Kelechukwu Favour(&lt;a href="https://dev.to/nulfacedesigner"&gt;https://dev.to/nulfacedesigner&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;GitHub: &lt;a href="https://github.com/im-kaycee" rel="noopener noreferrer"&gt;https://github.com/im-kaycee&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>githubchallenge</category>
    </item>
    <item>
      <title>Why I Stopped Flying Blind After Deploying My Side Projects</title>
      <dc:creator>Kelechukwu Amadi-Keke</dc:creator>
      <pubDate>Tue, 02 Jun 2026 09:27:52 +0000</pubDate>
      <link>https://dev.to/nulfacedesigner/why-i-stopped-flying-blind-after-deploying-my-side-projects-55da</link>
      <guid>https://dev.to/nulfacedesigner/why-i-stopped-flying-blind-after-deploying-my-side-projects-55da</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;For a long time, I treated deployment like a finish line.&lt;/p&gt;

&lt;p&gt;I’d spend weeks locked in a room building a project, finally push it to production, shoot the link to a few friends, and immediately start brainstorming the next idea. Job done, right?&lt;/p&gt;

&lt;p&gt;Except it wasn’t. The moment a project went live, it essentially entered a black box. I had no idea what was actually happening inside the code once it hit the wild. Were people clicking around? Which features did they actually care about? Was the API dragging its feet, or worse, quietly crashing while I was asleep?&lt;/p&gt;

&lt;p&gt;I had absolutely no clue. Now I know that's the wrong way to build a product.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Blind Spot
&lt;/h2&gt;

&lt;p&gt;The turning point came with a project that looked flawless from the outside. The landing page loaded fast, authentication was snappy, and everything seemed perfect. I had just built a tool that allows users find out where a picture was taken through GPS metadata and OCR-Geolocation.&lt;/p&gt;

&lt;p&gt;But then a friend texted me to complain that his uploads were failing. &lt;/p&gt;

&lt;p&gt;I was so confused, because it had worked the night before. It turned out a critical endpoint had been completely broken for three days. Because casual users don't track down your email to file a bug report—they just close the tab and never come back, I had been bleeding users without realizing it.&lt;/p&gt;

&lt;p&gt;That was the moment it clicked: If your users are discovering your bugs before you do, you’re flying blind.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 4 Questions Your App Needs to Answer
&lt;/h2&gt;

&lt;p&gt;Once your code is live, you shouldn't have to guess about its health. You need real-time answers to four fundamental questions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Is it even online? If your site goes down at 2:00 AM, do you find out via an automated alert, or do you wake up to an email from an annoyed user? Uptime monitoring isn't a luxury; it's a baseline.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Are people actually using it? Page views are a vanity metric. You need to know the narrative of your app: Which features are pulling weight, which pages are ghost towns, and where exactly are people getting frustrated and dropping off?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What's breaking right now? Again, silence does not mean success. Most users won't complain; they’ll just leave. If you aren't actively capturing stack traces and error logs, you're relying entirely on luck.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Is the API healthy? An API doesn't have to completely crash to be broken. If a database query bogs down and an endpoint takes eight seconds to respond, it's effectively dead to the user.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The Dashboard Fatigue (And Building observe)
&lt;/h2&gt;

&lt;p&gt;Naturally, the playbook answer here is to go sign up for tools. You get an account for product analytics, another for uptime, a third for error tracking, and maybe a fourth for API metrics.&lt;/p&gt;

&lt;p&gt;Before you know it, you’re drowning in tabs. I found myself constantly context-switching, jumping between four different dashboards just to get a basic pulse check on a simple side project. The data was there, but it was completely fragmented.&lt;/p&gt;

&lt;p&gt;Eventually, I got tired of the friction and decided to build a solution for my own sanity: &lt;a href="https://useobserve.xyz" rel="noopener noreferrer"&gt;observe.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbpacsgfv49r9l8wwun8i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbpacsgfv49r9l8wwun8i.png" alt="Observe Dashboard" width="800" height="382"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I didn't build it because the world desperately needed another developer dashboard. I built it because I wanted a single, unified view that instantly answered those four core questions without the overhead or cost. I was just tired of guessing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;We tend to celebrate the "ship it" moment, but deploying a project isn't the end of the narrative—it's just Chapter One.&lt;br&gt;
The moment your app interacts with real users is when the real learning begins. If you can’t see what’s happening beneath the hood, you’re making engineering and product decisions in the dark. And in software, flying blind always ends up being incredibly expensive.&lt;/p&gt;

</description>
      <category>monitoring</category>
      <category>programming</category>
      <category>api</category>
      <category>performance</category>
    </item>
    <item>
      <title>The Sustainability Question Around AI Models</title>
      <dc:creator>Kelechukwu Amadi-Keke</dc:creator>
      <pubDate>Thu, 09 Oct 2025 15:37:29 +0000</pubDate>
      <link>https://dev.to/nulfacedesigner/the-sustainability-question-around-ai-models-2efc</link>
      <guid>https://dev.to/nulfacedesigner/the-sustainability-question-around-ai-models-2efc</guid>
      <description>&lt;p&gt;There’s something about this AI wave that feels different from past tech cycles. The speed, the hype, the reach — it’s all unprecedented. But as everyone rushes to build, release, and integrate, I keep wondering: is any of this truly sustainable?&lt;/p&gt;

&lt;p&gt;When we talk about “sustainability” in tech, the first thing that comes to mind is usually environmental impact — energy use, carbon footprint, resource consumption. But with AI, sustainability goes deeper. It’s not just about how much power these models consume, but about the ecosystem that keeps them alive: compute, capital, and control. How much longer will AI tools be free/affordable?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Cost of Intelligence&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Someone in a discussion I had recently said something that’s really true: “These models are energy-intensive, and the current pricing structure isn’t sustainable.”&lt;/p&gt;

&lt;p&gt;That line stuck with me. Because when you look at the sheer scale of what it takes to run systems like GPT, Claude, or Gemini, it’s staggering. These aren’t static models sitting quietly in a data center. Every query, every API call, every chat or image generation spins up thousands of GPUs burning power at an industrial scale.&lt;/p&gt;

&lt;p&gt;It’s not just a matter of hardware — it’s the economics behind it. AI companies are in an arms race to make models smarter, faster, and more accessible, but each step up comes with exponential cost. Someone, somewhere, is paying that bill. Right now, it’s venture-backed firms and hyperscalers. But for how long?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Capitalist Engine Behind “Open” AI&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Others in that same conversation pointed to what’s maybe the less visible issue — the capitalist structure of modern tech. The people building the most powerful AI tools also own the platforms that distribute them, the servers that host them, and the companies that profit from their use.&lt;/p&gt;

&lt;p&gt;It’s a closed loop — and it’s hard to imagine true openness inside that.&lt;/p&gt;

&lt;p&gt;Even the supposedly “open” frontier models depend on infrastructure that’s owned by the same few companies. You can fork the code, train a small version, or deploy a fine-tuned variant — but in the end, you’re still renting your compute from the same giants who built the original models.&lt;/p&gt;

&lt;p&gt;It makes you wonder whether this ecosystem is designed for democratization or for deeper dependency.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A Possible Shift: Self-hosted and Smaller&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That’s why I find the rise of self-hosted models so interesting.&lt;/p&gt;

&lt;p&gt;Developers and organizations are beginning to realize they don’t always need a massive, general-purpose model. For many tasks, a small, domain-specific model is enough — and it can run locally, without cloud APIs or recurring costs.&lt;/p&gt;

&lt;p&gt;The tools are improving too. Frameworks like Ollama, vLLM, and Hugging Face’s inference tools are making it surprisingly easy to spin up your own LLM. You can fine-tune, host, and serve it privately.&lt;/p&gt;

&lt;p&gt;This shift feels like a quiet rebellion — not against AI itself, but against its centralization. It’s a movement back toward autonomy.&lt;/p&gt;

&lt;p&gt;And in that sense, it reminds me of the early days of open-source software — when people built because they could, not because it was profitable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Rise of Open and Chinese Models&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Another recurring point in these conversations is the growing presence of Chinese models and open alternatives.&lt;/p&gt;

&lt;p&gt;It’s not just diversity for diversity’s sake. It’s competition. Models like Yi, Qwen, and DeepSeek are advancing rapidly, and they’re breaking the Western monopoly over AI capability.&lt;/p&gt;

&lt;p&gt;That shift could be healthy for the industry. It introduces pressure — on pricing, access, and innovation. It forces transparency and keeps the power balance in check.&lt;/p&gt;

&lt;p&gt;In the long run, the end users — the developers, creators, and small startups — benefit from that competition. When there’s more choice, there’s more room for sustainability.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Quiet Dependency No One’s Talking About&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;But there’s another kind of sustainability we don’t talk about enough — workflow dependence.&lt;/p&gt;

&lt;p&gt;We’re entering a phase where an entire generation of developers is being shaped by AI-assisted tools. Things like Copilot, Replit AI, or N8N make development smoother, faster, and more enjoyable. They reduce friction and lower the barrier to entry.&lt;/p&gt;

&lt;p&gt;But they also shift ownership.&lt;/p&gt;

&lt;p&gt;When your entire workflow — your automation, your code generation, your pipelines — lives inside a closed ecosystem, you’re not working independently. You’re working inside a subscription model that can change, limit, or lock your access at any time.&lt;/p&gt;

&lt;p&gt;Take N8N for example. It’s one of the most exciting no-code automation tools out there, but it’s slowly drifting toward paywall-based limitations. You can self-host it, yes, but the message is clear: freedom is available, but convenience costs money.&lt;/p&gt;

&lt;p&gt;That’s the new dependency — not on a single model, but on the infrastructure of convenience.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Power, Cost, and Ownership&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When we talk about sustainability in AI, we often focus on energy usage or financial viability. But maybe the real sustainability question is about ownership.&lt;/p&gt;

&lt;p&gt;Who owns the models?&lt;br&gt;
Who owns the pipelines?&lt;br&gt;
Who owns the tools we use to create?&lt;/p&gt;

&lt;p&gt;Because if the answer to all three is “someone else,” then what we’re building isn’t a sustainable ecosystem. It’s a rental economy disguised as innovation. And if the majority of students, developers and other professionals are hooked on these tools that have suddenly been made expensive, we might be looking at the new “white gold”.&lt;/p&gt;

&lt;p&gt;The future we seem to be moving toward is one where access replaces ownership, convenience replaces control, and automation replaces understanding. And maybe that’s fine for some — but it shouldn’t be the only path forward.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where we go from here&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There’s still hope in the small things. The open-source communities building local models. The engineers writing papers outside corporate labs. The creators pushing for smaller, decentralized systems that can thrive independently.&lt;/p&gt;

&lt;p&gt;That’s where sustainability might actually live — not in the biggest data centers or the most powerful models, but in the ability to build, host, and maintain tools on our own terms.&lt;/p&gt;

&lt;p&gt;AI doesn’t have to be unsustainable. But it does need to evolve beyond this cycle of scale and dependency. Otherwise, we’ll wake up one day surrounded by incredible tools — none of which we actually own or understand.&lt;/p&gt;

&lt;p&gt;And that’s not intelligence. That’s just another form of control.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>discuss</category>
      <category>llm</category>
    </item>
    <item>
      <title>I Failed My First Software Engineering Interview — And Here’s What I Learned</title>
      <dc:creator>Kelechukwu Amadi-Keke</dc:creator>
      <pubDate>Sun, 28 Sep 2025 22:09:17 +0000</pubDate>
      <link>https://dev.to/nulfacedesigner/i-failed-my-first-software-engineering-interview-and-heres-what-i-learned-10h4</link>
      <guid>https://dev.to/nulfacedesigner/i-failed-my-first-software-engineering-interview-and-heres-what-i-learned-10h4</guid>
      <description>&lt;p&gt;On Wednesday this week, I had my very first interview for an internship role at a software engineering company. Nerves were high, the stakes felt even higher, and I wasn’t sure what to expect.&lt;/p&gt;

&lt;p&gt;I joined the call, introduced myself to the interviewer, and we got started. Things began smoothly… until they didn’t.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Beginning&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The interviewer started with the classic question: &lt;em&gt;“Tell me about yourself.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I had prepared well for this, so I answered confidently. We quickly moved on to my projects. He focused on my blockchain-based voting system and asked me to explain the architecture, data flow, and the essential parts of the app.&lt;/p&gt;

&lt;p&gt;I walked him through the user interface, the smart contract functions, the backend, and how I used the MVT framework to tie it all together. Up to this point, everything felt great.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mid-Interview&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Then came the first curveball: &lt;em&gt;“Why did you make XYZ design choice?”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I froze for a second. I knew that design had a flaw that would hurt performance in large-scale elections, but I hadn’t fixed it due to time constraints. I went into defensive mode, explained the flaw, and then talked about how I could fix it in future iterations. Luckily, that seemed to land well.&lt;/p&gt;

&lt;p&gt;But then he followed with: “Your projects are cool, but your stack doesn’t really fit ours. How quickly can you adapt?”&lt;/p&gt;

&lt;p&gt;This caught me off guard, but I shared how I had quickly adapted to Solidity when working on the voting system. That seemed to reassure him, and we moved to the final stage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Interview End&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The interviewer asked a few Python questions — my strongest language. I was ready… until he asked about two very basic concepts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Asynchronous programming&lt;/li&gt;
&lt;li&gt;Mutability of data structures&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For reasons I still don’t understand, I blanked. I stuttered, gave answers that weren’t entirely wrong, but weren’t textbook definitions either.&lt;/p&gt;

&lt;p&gt;I heard the sigh on the other end. In that moment, I knew the truth: I wasn’t getting the job.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lessons Learned&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This interview humbled me. It made me question whether I was truly good enough, whether I really knew my stuff, and whether I even belonged in this space.&lt;/p&gt;

&lt;p&gt;But after reflecting, I realized a few things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One interview isn’t the end. There will be many more, and better opportunities will come.&lt;/li&gt;
&lt;li&gt;Interviews are a skill of their own. Preparing for interviews is almost like a full-time job, and fumbling doesn’t mean you’re not a good developer.&lt;/li&gt;
&lt;li&gt;Failure is feedback. I now know exactly what to revise, and where to sharpen my knowledge.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Walking away, I didn’t get the offer — but I gained something else: clarity on what to improve, and confidence that the next time will be better.&lt;/p&gt;

</description>
      <category>career</category>
      <category>interview</category>
      <category>beginners</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>How I Built a Blockchain Voting System (And What I Learned in 4 Days)</title>
      <dc:creator>Kelechukwu Amadi-Keke</dc:creator>
      <pubDate>Sun, 21 Sep 2025 23:58:04 +0000</pubDate>
      <link>https://dev.to/nulfacedesigner/how-i-built-a-blockchain-voting-system-and-what-i-learned-in-4-days-18p</link>
      <guid>https://dev.to/nulfacedesigner/how-i-built-a-blockchain-voting-system-and-what-i-learned-in-4-days-18p</guid>
      <description>&lt;p&gt;I was doomscrolling on YouTube sometime around December last year, when I came across a video by Cleo Abram where she explained why the United States did not make use of E-Voting systems to carry out the 2024 General Elections. While I can’t explain everything she said in the video, it got me thinking: &lt;em&gt;“Can All These Issues Be Solved via Decentralization? ”&lt;/em&gt;.  This motivated the application I built for my final year project.&lt;br&gt;
For my final year project, I built a blockchain-based voting system that uses smart contracts to make elections transparent, tamper-resistant, and verifiable. The idea was simple: every vote is recorded on the blockchain, and no one can change the results once they’re in.&lt;/p&gt;

&lt;p&gt;In this guide, I’ll walk you through what building such a system entails from a developer’s perspective — the architecture, the smart contract design, how the frontend interacts with the blockchain, and some of the challenges I faced along the way. I will not be speaking in any programming language specific terms, so as to give everyone an understanding of the system.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Problem Statement &amp;amp; Goals&lt;/strong&gt;&lt;br&gt;
The system was aimed at addressing two main issues. Simplicity for non-technical voters, and Security/Transparency of cast votes. This meant that the voting interface was made as easy as possible to understand, while votes were stored in the blockchain for security and displayed to users in real time for transparency.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;High-Level Architecture&lt;/strong&gt;&lt;br&gt;
The system was designed with a semi-decentralized architecture in mind. Instead of a completely decentralized system, the registration of voters is done by an electoral commission, and login credentials given to the voters to login. &lt;/p&gt;

&lt;p&gt;At its core, the voting system I built has three main parts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The smart contract: this lives on the blockchain and is responsible for storing candidates, recording votes, and making sure no one can cheat (for example, by voting twice).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The frontend interface: this is what the voter sees: a simple page where they can connect their wallet, view candidates, and cast a vote.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The backend/indexer: this listens to blockchain events and stores them in a database so results can be shown quickly and cleanly, without querying the chain every time.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here’s how they work together: the frontend lets a voter choose a candidate → their wallet signs the transaction → the smart contract records the vote on-chain → the results can be read either directly from the contract or through the backend, which makes things faster and easier to display.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbvznd0ogowq5bvdkf1op.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbvznd0ogowq5bvdkf1op.png" alt="Use Case diagram for system" width="418" height="558"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I deliberately kept most of the logic on-chain so that security and transparency were guaranteed. The trade-off is that everything stored on the blockchain is public, but for the purposes of my project, that was acceptable since the main goal was to prove tamper-resistance and verifiability.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Smart Contract Design&lt;/strong&gt;&lt;br&gt;
The smart contract, written in Solidity, handled verification of authenticity of votes, vote storage and retrieval via some major functions. The first function was triggered when the backend sent the list of candidates to the contract for storage. This meant that only votes related to these candidates would be allowed. The second function handled vote validation and storage and was triggered when an event (Vote Casting) was triggered. This function retrieved the ID of the voter and the ID of the candidate that was voted for. This is then hashed to ensure it remains secure and is stored on the blockchain. The last function simply sends the number of votes cast for each candidate back to the backend for display on the frontend.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   function vote(uint256 candidateId) public {
        require(!hasVoted[msg.sender], "You have already voted.");
        require(candidates[candidateId].id == candidateId, "Invalid candidate.");

        candidates[candidateId].voteCount += 1;
        hasVoted[msg.sender] = true;

        emit VoteCasted(msg.sender, candidateId);
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Furthermore, some constraints were implemented on the contract. Only one vote can be cast per address (User). Casting more than one vote will trigger an error and reject the vote.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Development Workflow&lt;/strong&gt;&lt;br&gt;
Some of the tools used for development included Remix IDE for writing and deploying Solidity smart contracts to the Ganache Ethereum testnet which was used to simulate the blockchain network.&lt;br&gt;
The frontend was developed using HTML, CSS and JavaScript and retrieved data from the backend via API requests. The backend was developed using the Django framework which allowed for ease of scale in the long term and communicated with the smart contract via web3.py. So it was essentially a middleman between the frontend and the smart contract.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Challenges Faced and Lessons Learned&lt;/strong&gt;&lt;br&gt;
Building this system was a roller-coaster especially because I had four days to do so and in the course of this, many challenges were faced and many lessons learned. Some of these challenges included the complexity of working with a new language as I hadn’t worked with Solidity prior to this. Although not a major issue, scalability of the system was another issue faced as the speed of the system reduced as more voters were added to the system but given the fact that this was just a prototype, it was negligible.&lt;br&gt;
Gas fees and cost of transactions was not an issue given the fact that this was done on the Ganache testnet, but in a live system, gas optimization will definitely be something to look into.&lt;/p&gt;

&lt;p&gt;What do you think? Is a semi-decentralized model the right approach for secure digital voting? Have you built something similar? I'd love to hear your thoughts in the comments!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>blockchain</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
