MY JOURNEY AS A DEVELOPER

Published: (February 16, 2026 at 10:54 AM EST)
7 min read
Source: Dev.to

Source: Dev.to

Level 1: Lunartech

The Beginning: The Experimentation Mindset

Hello readers, my name is Jim Amuto, and this is my story. One thing about me is that I love experimenting. In every project I do, I don’t follow the norm. I ask myself:

  • What am I doing?
  • What is the end goal?
  • How much faster can I ship it to actual users or increase my workflow speed?

That curiosity turned into a passion for software development, especially DevOps. I’m grateful for my current position because it let me spot loopholes and the need to ship code faster.

The Challenge: Full‑Stack in an AI Startup

I remember being on a deadline with a mountain of tasks. In an AI startup you’re often required to wear many hats—full‑stack roles instead of a narrow specialization. That’s great for becoming a “jack of all trades” and later focusing on a niche as you grow.

Shipping Code Under Pressure

My big project was an AI translator that had to handle long‑form content—something my boss insisted on. The device I was using became a bottleneck; AI/ML workloads are computationally intensive, but there are no excuses. I tried repeatedly until it failed.

I reached out to a friend with a more powerful machine. We hopped on a call, he cloned the repo, and I told him what to install first. He ran a dependency‑install script and—literally—dependency hell erupted. He fixed what he could, but the build still failed because of a maze of specific version requirements. I eventually told my boss that my PC wasn’t enough.

I researched cloud computing and found many GPU/CPU rental options, but I didn’t have the budget. I suggested the idea to my boss and waited for feedback—a painfully long wait.

The Revelation: Why Docker?

Why am I telling you this? I had a revelation: if my code couldn’t run on my friend’s setup, how could I expect it to run in production?

Time was ticking. I had multiple Jira tickets, and two months in I still hadn’t completed them. Some tasks—like building a simple progress tracker—looked easy on paper but stalled because of stack incompatibilities.

At that point I accepted that the frontend could be harder than the backend. A broken progress tracker is non‑negotiable; no user wants to see it. The pressure to finish was intense, and I almost gave up.

Then I thought: maybe my approach is wrong. I dug deeper, researched, and decided to try Docker to package my code.

Docker is a tool that packages everything your code needs into an image that can spin up isolated, ephemeral container instances.

The Docker Gamble

Docker was a big gamble for me. It took hours to implement and came with many reality checks:

  • Long build times.
  • My AI coding agent (the “assistant”) kept performing actions I wouldn’t attempt now, erasing progress and forcing me to backtrack.

I sat down, planned with the agent, and asked:

  • Why rebuild this and not that?
  • When should I clear the cache and volumes?

These questions saved me hours that I’d previously wasted restarting containers instead of rebuilding them to capture new dependencies.

I enabled hot‑reload by binding the host code directory to the services (backend and frontend). The containers could instantly see my changes without a rebuild—a game‑changer that sped up my workflow while keeping the environment isolated.

The Persistence Challenge

Everything was smooth until I needed the application to survive restarts. Docker containers keep commands running continuously, so I didn’t have to restart a terminal to see changes, but the frontend still needed to reflect those changes.

My stack includes:

  • Next.js – frontend
  • FastAPI – backend
  • Numerous model dependencies
  • Ollama – local LLM serving

The Ollama Experiment

Why Ollama? I jumped on the hype train that local models protect data, have no rate‑limiting, and are free to query.

I was building a translator. Using external APIs gave literal, context‑less translations. I scoured the internet for free models—painful, but that’s the trade‑off.

My boss sent me a link to TranslateGemma, an open‑source Google model. It was perfect at the time, and a pre‑built Ollama image existed, so I ran:

ollama pull translategemma:4b

My system couldn’t handle the 12B/27B parameter versions, but I was committed. I set up an Ollama container and everything worked for a few days.

When I tested long‑running content, Ollama ate all the memory allocated to the container, causing the resources to run out. I switched to running Ollama locally.

Question: If it consumes that much memory, is it viable in production? The answer implied high costs—something I kept in the back of my mind.

Enter Redis: The Swiss Army Knife

My project has two login methods:

  1. Demo login – for fast prototyping (boss insisted).
  2. Auth login – production‑grade authentication.

I built the demo login using local storage, which was quick but not secure. To unify the two flows and add a caching layer for session data, I introduced Redis. It became the “Swiss Army knife” of my stack, handling:

  • Session storage
  • Rate‑limiting for API calls
  • Simple key‑value caching for model outputs

Redis allowed the demo and auth logins to share a common session store, making the transition from prototype to production smoother.

Takeaways

  1. Never assume your dev machine reflects production.
  2. Docker isolates dependencies and eliminates “it works on my machine” headaches.
  3. Hot‑reload via bind mounts dramatically speeds up iteration.
  4. Local LLM serving (Ollama) is great for data privacy but can be memory‑hungry; always benchmark for production.
  5. Redis is an underrated tool for session management and lightweight caching in a full‑stack AI app.

My journey from dependency hell to a production‑grade setup taught me that the right tooling—and a willingness to experiment—can turn impossible deadlines into manageable milestones.

In Memory

I set aside the auth login for later and spent most of my time in demo mode so that whenever my boss requested progress, I could provide it immediately.

However, storing outputs in local memory contradicted the requirement for the app to survive restarts because local memory wouldn’t work in production. So I had to find a solution.

That’s when I discovered Redis, a small, lightweight instance with many uses—from caching to persistent storage. It was very fast. At first, I used it as storage for my demo jobs since I wasn’t using a database, and it worked perfectly.

Unlocking Redis’ Potential

Later, I realized I wasn’t using Redis to its full potential. I had my backend send APIs to Redis to query task progress, and the frontend fetched progress from the backend—but that failed.

I tried using WebSockets to update progress, and it worked partially. I was excited, especially since I needed progress bars for five tasks.

The Final Piece: Celery

I had often heard that Redis and Celery go hand in hand. I used to wonder what RabbitMQ and Kafka were. It turns out they are message brokers. Once again, my superhero Redis could act as both a message broker and a task queue—that’s four roles.

Celery, as I understand it, is the worker that:

  1. Offloads tasks from the task queue.
  2. Processes them.
  3. Sends a completion message to the broker to notify the frontend to fetch results.

It took me hours to implement, but this was genuinely one of the best things I have ever done. It fixed so many issues. I realized FastAPI was part of the problem—it couldn’t handle many concurrent tasks asynchronously the way I needed. That’s why I never got proper updates before.

Now all my progress trackers work, and all I have left to do is make the progress bars look uniform.

To be continued…

0 views
Back to Blog

Related posts

Read more »

Preface

Motivation I wanted to record my studies to have consistency. Since I don't directly learn building projects from my CS program, I want to be an expert in my a...