<?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: Mazen Aly</title>
    <description>The latest articles on DEV Community by Mazen Aly (@mazenaly256).</description>
    <link>https://dev.to/mazenaly256</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3951938%2F197107da-8d37-4fb6-9f1a-5c8029f96024.png</url>
      <title>DEV Community: Mazen Aly</title>
      <link>https://dev.to/mazenaly256</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mazenaly256"/>
    <language>en</language>
    <item>
      <title>Part 2: Designing the Database Schema and Data Representation</title>
      <dc:creator>Mazen Aly</dc:creator>
      <pubDate>Mon, 17 Aug 2026 12:51:47 +0000</pubDate>
      <link>https://dev.to/mazenaly256/part-2-designing-the-database-schema-1ck1</link>
      <guid>https://dev.to/mazenaly256/part-2-designing-the-database-schema-1ck1</guid>
      <description>&lt;h3&gt;
  
  
  Main Entities
&lt;/h3&gt;

&lt;p&gt;While designing the database through an ERD, I found that the main entities are &lt;strong&gt;users&lt;/strong&gt;, &lt;strong&gt;boards&lt;/strong&gt; (that represent projects), &lt;strong&gt;columns&lt;/strong&gt; (that represent stages) and &lt;strong&gt;tasks&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I designed the system's data model to be user-owned data, so every user is admin of the boards that are created by them, and there is no admin role that give full control on all the data.&lt;/p&gt;

&lt;h4&gt;
  
  
  Database Relational Schema
&lt;/h4&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frm9cmg4qvdzvi8qdxuz2.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frm9cmg4qvdzvi8qdxuz2.png" alt="Database Relational Schema" width="798" height="221"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Roles
&lt;/h3&gt;

&lt;p&gt;I decided to have four roles: &lt;strong&gt;Owner&lt;/strong&gt;, &lt;strong&gt;Manager&lt;/strong&gt;, &lt;strong&gt;Assignee&lt;/strong&gt; and &lt;strong&gt;Viewer&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Owner:&lt;/strong&gt; is given automatically to the user that created the board/project, allowing them to perform project-level CRUD operations in addition to CRUD operations against the columns.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Manager:&lt;/strong&gt; allows performing task-level CRUD operations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Assignee:&lt;/strong&gt; can only change the status of a task (by transferring it from a column to another)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Viewer:&lt;/strong&gt; can not take any action, can only view the board details (giving the access to the project data).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We need another table to store the role of each user per board/project, so &lt;strong&gt;user_board_role table&lt;/strong&gt; is the only place where the permissions/roles are saved.&lt;/p&gt;

&lt;p&gt;So, totally we need 5 tables: users, boards, columns, tasks and user_board_role&lt;/p&gt;

&lt;p&gt;Also we need a table to store the events that happens, but this will be added when we setup the event-driven architecture for the system.&lt;/p&gt;




&lt;h3&gt;
  
  
  Handling the Order of Tasks in a Column
&lt;/h3&gt;

&lt;p&gt;In the tasks table we need to preserve the order of the tasks, so when retrieving the tasks for a specific column, we need to sort them by their order.&lt;/p&gt;

&lt;h4&gt;
  
  
  Possible Inefficient Solution
&lt;/h4&gt;

&lt;p&gt;A naive solution for this is to have a column inside the tasks table that stores a number representing the order of the task (index of the task).&lt;br&gt;
However, this solution is inefficient as when we need to change the order of a specific task, we need to update all the tasks between its old position and new position and increase the number that represents their order by 1.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;time complexity&lt;/strong&gt; of this algorithm is O(n), as for each task we need to change we have to loop over all the tasks between its new and old positions and update them.&lt;/p&gt;

&lt;h4&gt;
  
  
  The Chosen Efficient Solution
&lt;/h4&gt;

&lt;p&gt;The more efficient approach is to store the order as a decimal (fractional index). So when we need to change the position of a specific task, all we need is to find a decimal between the index of the previous and next task to be the new index of the transferred task. We sort the tasks according to their index to get a sorted list of tasks.&lt;/p&gt;

&lt;p&gt;For example, task A has index 1, task B has index 2, dropping a new task between them requires calculating a new index for the new task that is 1.5.&lt;/p&gt;

&lt;p&gt;Its time complexity is only O(1), so it is very efficient. However, after many operations we may face precision problems, the solution is to &lt;strong&gt;rebalance&lt;/strong&gt; when two adjacent indices get too close in value to fit a new decimal between them. Rebalancing is just looping over the tasks and assigning them integer-valued indices.&lt;/p&gt;

</description>
      <category>database</category>
      <category>design</category>
    </item>
    <item>
      <title>Part 1: Determining What to Build</title>
      <dc:creator>Mazen Aly</dc:creator>
      <pubDate>Sun, 16 Aug 2026 17:03:35 +0000</pubDate>
      <link>https://dev.to/mazenaly256/part-1-choosing-the-idea-3c92</link>
      <guid>https://dev.to/mazenaly256/part-1-choosing-the-idea-3c92</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;This is the first post of a series that documents the whole journey of my third major production-grade project. It is going to contain the whole process from an idea in my mind to a &lt;strong&gt;fully deployed web application&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Determining What I'm Going to Build
&lt;/h2&gt;

&lt;p&gt;I wanted to tackle a new challenge centered around real-time systems and complex state management. I also wanted to explore caching strategies and other infrastructure concerns like event-driven architecture.&lt;/p&gt;

&lt;h3&gt;
  
  
  The First Choice, and Why I Passed on It
&lt;/h3&gt;

&lt;p&gt;My first idea was a live collaborative text editor as a real-time application. But after researching the problem space, I realized that its core engineering challenges (like document synchronization, cursor synchronization, and conflict resolution) are highly specialized problems that are not closely aligned with the areas I want to grow in: backend engineering, system design, and architectural decision-making.&lt;/p&gt;

&lt;p&gt;More importantly, these problems are already solved by mature libraries such as Yjs, paired with editor frameworks like Lexical or Monaco. In a real-world project, integrating these libraries is the right engineering decision rather than spending significant time reimplementing this highly specialized logic, which offers limited learning beyond that narrow domain.&lt;br&gt;
As a result, the project's primary distinguishing feature, that is live collaborative editing, is provided by third-party software.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Second Choice, and Why It Was The Right Fit
&lt;/h3&gt;

&lt;p&gt;After some searching, I found that a collaborative project management platform is a good choice. It naturally introduces a wide range of engineering challenges that add real value to the system. Unlike a collaborative text editor, these challenges arise from the domain itself rather than being artificially introduced to justify additional technologies. They include caching, event-driven workflows, notifications, background processing, authorization, audit logging, search, and real-time synchronization, all working together to support the final product. These are exactly the kinds of problems encountered in production backend systems, providing far more opportunities to practice system design and architectural decision-making.&lt;/p&gt;

&lt;p&gt;In the end, my goal wasn't simply to build a real-time application. It was to build a system whose domain inherently demands diverse architectural decisions and production-grade engineering challenges, allowing me to learn far more than a project centered around a single specialized problem.&lt;/p&gt;




&lt;h2&gt;
  
  
  Choosing the Web Framework
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Why not ASP.NET
&lt;/h3&gt;

&lt;p&gt;I had already built two projects using ASP.NET Core and the .NET ecosystem, so I wanted this project to expose me to a different ecosystem.&lt;/p&gt;

&lt;p&gt;I chose Python because it is widely used beyond web development in areas such as automation, AI, and data engineering. Rather than building another project with tools I already knew well, I wanted this project to broaden my technical perspective.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why FastAPI
&lt;/h3&gt;

&lt;p&gt;It's a modern, asynchronous web framework with first-class WebSocket support, making it a natural fit for building real-time applications. Unlike Django and Flask, which require additional libraries or extensions to build WebSocket-based applications, FastAPI provides this capability out of the box.&lt;/p&gt;

&lt;p&gt;Furthermore, it has a significantly lighter configuration model than ASP.NET Core, allowing me to move from project setup and infrastructure configuration to implementing application logic much more quickly. This provides a streamlined development experience with minimal boilerplate, enabling me to focus more on the engineering challenges of the project rather than framework configuration. It also provides many capabilities out of the box, including dependency injection, automatic request validation, and OpenAPI documentation with very little configuration in addition to being a high-performance web framework.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;In the next post, I'll dive into the details of the project, some capabilities of the system and database design.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>backend</category>
      <category>softwaredevelopment</category>
      <category>webdev</category>
    </item>
    <item>
      <title>LINTelligent — AI-Integrated service for code linting and reviewing with MCP server</title>
      <dc:creator>Mazen Aly</dc:creator>
      <pubDate>Mon, 20 Jul 2026 07:17:07 +0000</pubDate>
      <link>https://dev.to/mazenaly256/lintelligent-ai-integrated-service-for-code-linting-with-mcp-server-4ke4</link>
      <guid>https://dev.to/mazenaly256/lintelligent-ai-integrated-service-for-code-linting-with-mcp-server-4ke4</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;This is a post I need to share with you my thought process, decisions that I took in designing the service, and share new things that I learned. I hope anyone can benefit from my words or inspire anyone with my ideas and what I learned so we both can grow. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub Repository:&lt;/strong&gt; &lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/mazenaly256" rel="noopener noreferrer"&gt;
        mazenaly256
      &lt;/a&gt; / &lt;a href="https://github.com/mazenaly256/LINTelligent" rel="noopener noreferrer"&gt;
        LINTelligent
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      AI-integrated backend service for code linting (i.e. analyzing code for issues), with an accompanying MCP server for AI-agent integration.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;LINTelligent&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;em&gt;AI-integrated backend service for code linting (i.e. analyzing code for issues), with an accompanying &lt;strong&gt;MCP server&lt;/strong&gt; for AI-agent integration.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/mazenaly256/LINTelligent/actions/workflows/ci-pipeline.yml/badge.svg"&gt;&lt;img src="https://github.com/mazenaly256/LINTelligent/actions/workflows/ci-pipeline.yml/badge.svg" alt="CI Pipeline Building and Testing"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Overview&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;A code snippet is submitted in a linting/reviewing request, either as a direct snippet in the request body or via a public GitHub file URL.&lt;/p&gt;
&lt;p&gt;Once the linting request reaches the system, &lt;em&gt;LINTelligent&lt;/em&gt; saves its details in the database and enqueues a background job to the job queue for handling this request, then immediately returns 202 Accepted. If a GitHub URL was provided, the code is first fetched, then the review job runs, otherwise the review job runs directly on the submitted code snippet.&lt;/p&gt;
&lt;p&gt;After that, a worker picks up the job from the job queue and processes it, it fetches the code from the GitHub URL (if exists) then it calls the configured LLM provider with the request details and receive the review report of issues, then updates…&lt;/p&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/mazenaly256/LINTelligent" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Fun Fact:&lt;/strong&gt; While I was testing it and request reviews on some code snippets from my previous project (Cinema Seat Reservation System), LINTelligent helped me discover a critical bug related to resource wasting as I did not dispose some objects that results in memory leak.&lt;/p&gt;




&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;LINTelligent is a service that takes a code snippet as an input, and analyze it and return the issues in this code snippet.&lt;/p&gt;

&lt;p&gt;User can either use it directly by requesting the API endpoints, or via an AI agent through the MCP server.&lt;/p&gt;

&lt;h3&gt;
  
  
  The workflow
&lt;/h3&gt;

&lt;p&gt;User sends a review request, the service stores a new review with the code snippet in the database with status 'Pending', then it stores in the queue the methods that should be called to process this job/request with the related arguments for this request, then the service immediately returns 202 Accepted HTTP response so the client do not wait too much, &lt;strong&gt;detaching the client from long-running background processing&lt;/strong&gt;.&lt;br&gt;
As the jobs are saved in the queue, a worker thread picks up a job of a review request from the queue and process it, calling the methods that are stored in database as the processing way for this job. The worker sends the review request with the &lt;strong&gt;system prompt&lt;/strong&gt; and the code snippet (user message) to the LLM and receives the response, then the service persists the review report that LLM returned into the database, then it notifies the user that the the request processing has been finished.&lt;/p&gt;


&lt;h2&gt;
  
  
  System Architecture and Design
&lt;/h2&gt;

&lt;p&gt;Lets start with a basic system architecture diagram with the data flow for the service.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkbjf6w5rsutk4dswkcee.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkbjf6w5rsutk4dswkcee.png" alt="Basic System Architecture Diagram" width="800" height="417"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Asynchronous Processing
&lt;/h3&gt;

&lt;p&gt;I designed this system to handle the requests in an asynchronous way, so the requests are processed in the background and then the user gets notified on completion via webhook. To achieve this I used &lt;strong&gt;message/job queue pattern&lt;/strong&gt;, as shown in the diagram, the service stores the review request as a job in the job queue, and then a worker execute that job by calling the LLM, getting the review report then notify the user via webhook.&lt;/p&gt;
&lt;h4&gt;
  
  
  Queue Pattern
&lt;/h4&gt;

&lt;p&gt;The queue pattern is simply a pattern where a &lt;strong&gt;producer&lt;/strong&gt; puts messages/jobs in a &lt;strong&gt;queue&lt;/strong&gt;, and then a consumer/worker (that can be either on another machine or just another thread) that reads that job/message and executes some logic to process them.&lt;/p&gt;

&lt;p&gt;In our case, the &lt;strong&gt;producer is obviously the service&lt;/strong&gt;. Inside the endpoint of requesting a new review, it stores a job in a queue.&lt;/p&gt;

&lt;p&gt;Now we need a queue that persists the jobs/messages so the workers can take and process them one by one. Also, we need the workers themselves.&lt;/p&gt;
&lt;h4&gt;
  
  
  Hangfire Decision
&lt;/h4&gt;

&lt;p&gt;Hangfire is a technology that provides the queue and persist the jobs data in a database (stores the details about the method that is required to be called to process some logic).&lt;/p&gt;

&lt;p&gt;Also Hangfire reserves a number of threads form the thread pool of the application to create the workers pool, these are threads that only execute the enqueued jobs, each worker polls for jobs from the database and when there is a job it directly execute it.&lt;/p&gt;

&lt;p&gt;Because of that, I favored using Hangfire to implement this pattern. It is simpler and provide all-in-one solution for me and at my scale I believe that it is more than sufficient.&lt;/p&gt;

&lt;p&gt;Other choices would be more complicated and will not pay off at my scale. I could implement this using a separate queue on another server via technologies like &lt;strong&gt;RabbitMQ&lt;/strong&gt; or any similar message brokers but this will require having separate workers also that will listen to the messages or poll for them and implement the logic.&lt;/p&gt;


&lt;h3&gt;
  
  
  Handling User-Supplied URLs Safely (SSRF Mitigation)
&lt;/h3&gt;

&lt;p&gt;When I added the ability to submit a GitHub file URL instead of pasting code directly, I ran into a security problem that's easy to miss: SSRF, or Server-Side Request Forgery.&lt;/p&gt;

&lt;p&gt;The naive version of this feature is simple, take the URL the user gives you, and have your server fetch it. The problem is that "your server fetches it" part. The request doesn't come from the user's browser, it comes from your backend, using your backend's network position. If you don't restrict what URLs are allowed, an attacker isn't limited to real GitHub files, they can point your server at internal services, cloud metadata endpoints, or anything else your server can reach that the hackers normally couldn't.&lt;/p&gt;

&lt;p&gt;So a URL field isn't just an input validation problem, it's a "what is my server willing to do on someone else's behalf" problem.&lt;/p&gt;

&lt;p&gt;For handling this, I enforced exact host match on &lt;code&gt;raw.githubusercontent.com&lt;/code&gt;, and prevented any redirections when requesting the submitted URL.&lt;/p&gt;


&lt;h3&gt;
  
  
  Integration with LLM and controlling the usage cost
&lt;/h3&gt;

&lt;p&gt;When you call the LLM to integrate it in your system, you don't just send the code. You send two things every single call:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. System Prompt&lt;/strong&gt;&lt;br&gt;
This is your instructions to the LLM, it never changes between calls. It tells the LLM who it is (the persona) and what to do. It is something like:&lt;br&gt;
"You are a code review assistant. Analyze the code you receive and return ONLY a JSON object with an issues array. Each issue must have: line number, severity (error/warning/info), type, and message. Never explain yourself. Never add text outside the JSON."&lt;br&gt;
This is how you force structured output, short and structured JSON and nothing else. Without it, the AI would respond in plain English like a human, and this is hard to process in the code also it makes your output tokens explode and thereby your cost.&lt;/p&gt;

&lt;p&gt;That's exactly why the system prompt exists, to say "return JSON only, no explanations", it's not just about structure, it's also cost control. Furthermore, you handle edge cases through the system prompt, like telling the LLM that if the inferred language of the code snippet does not match the language field that is sent with the request, then return language mismatch, instead the LLM returns many compilation errors as the language is different, which is unnecessary cost.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. User Message&lt;/strong&gt;&lt;br&gt;
This is the actual code the user submitted, and LLM deals with it according to the instructions in the system prompt. This changes every call according to the request data, this is the "What to handle". System prompt is the "How to handle".&lt;/p&gt;


&lt;h3&gt;
  
  
  Software Design (Architecture and Patterns)
&lt;/h3&gt;

&lt;p&gt;I was building my application without caring about this at the beginning, but when I needed to perform &lt;strong&gt;Unit Testing&lt;/strong&gt;, I realized that my code is tightly coupled and needs refactoring. So, in the next sections I will specify what did I design and build exactly.&lt;/p&gt;
&lt;h4&gt;
  
  
  Clean Architecture
&lt;/h4&gt;

&lt;p&gt;When thinking in this project, it appears that it aligns well with the Clean Architecture. It has external dependencies like database, LLM, webhook notifying and GitHub integration, so they should be isolated in &lt;strong&gt;Infrastructure Layer&lt;/strong&gt;. Inside this layer, I designed it to contain implementations for LLM clients that their job is only to communicate with LLM providers and it absolutely never do anything related to the business logic, and to contain implementations for repositories. Then I built an &lt;strong&gt;Application Layer&lt;/strong&gt; that orchestrate the business workflow and decisions, so it talks to the infrastructure layer without being dependent on it, achieving loose coupling between layers.&lt;/p&gt;

&lt;p&gt;This aligns with the &lt;strong&gt;Single Responsibility Principle&lt;/strong&gt;. Also, it makes the codebase more &lt;strong&gt;testable&lt;/strong&gt; as it isolates the client and make all the business workflow orchestration only inside the Application Layer. Now if I want to write unit tests, I will never care about the client as it is simply integration details, no need to consider them in unit testing.&lt;/p&gt;
&lt;h4&gt;
  
  
  Adapter design pattern
&lt;/h4&gt;

&lt;p&gt;Appears in LLM client. It adapts the different responses of different LLMs, and give standard response to the Application Layer. So, the client itself adapts the internal shape of data to be compatible with the standard DTO defined inside the Application Layer.&lt;/p&gt;
&lt;h4&gt;
  
  
  Repository Design Pattern
&lt;/h4&gt;

&lt;p&gt;Generally, having repository pattern with EF Core is actually a bad practice. The truth is EF Core itself applies repository pattern and unit of work pattern. So if you tried to implement repository pattern, it will be just wrapper methods over the EF Core, and it will hide the power of using EF Core directly and controlling the queries and commands via LINQ.&lt;/p&gt;

&lt;p&gt;But in my case, I decided to have a repository pattern, actually I felt that it is important. In my case I just need some operations like: changing status, saving review result in the database or get review by ID. I did not need to delete anything or to generally update the records, I just needed to update specific fields and add new or get by ID, so in my case I found that it is better to have this layer that will introduce to me better API to use inside the application layer and fits better to my needs. Furthermore, the repository pattern here to achieve more loose coupling, and higher testability by using the interfaces and mocking, so it is a trade-off.&lt;/p&gt;


&lt;h2&gt;
  
  
  Integrating with the AI Agent
&lt;/h2&gt;

&lt;p&gt;I wanted to explore what it means to make a service agent-ready, not just API-ready. I wanted to make the AI agent to become another consumer of the API, so not only frontend clients can use my service via APIs, also the AI agents via &lt;strong&gt;MCP Server&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  What is MCP Server
&lt;/h3&gt;

&lt;p&gt;AI Agent (more accurately, Host) contains two relevant pieces: the LLM (that is responsible for the reasoning) and the Client (that communicates with MCP servers).&lt;/p&gt;

&lt;p&gt;The MCP server is essentially a layer for AI agents to use the API. REST API endpoints are great for developers building frontends that consume the API directly, but if you want AI agents to call your API endpoints, then you need this extra layer, the MCP server, communicating with AI agent either over stdio or HTTP, depending on whether it runs locally on the same machine as the agent, or the server is deployed online.&lt;/p&gt;
&lt;h4&gt;
  
  
  Docker Image
&lt;/h4&gt;

&lt;p&gt;Docker image of the local MCP server is available in the packages section in the repository.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/mazenaly256" rel="noopener noreferrer"&gt;
        mazenaly256
      &lt;/a&gt; / &lt;a href="https://github.com/mazenaly256/LINTelligent" rel="noopener noreferrer"&gt;
        LINTelligent
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      AI-integrated backend service for code linting (i.e. analyzing code for issues), with an accompanying MCP server for AI-agent integration.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;LINTelligent&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;em&gt;AI-integrated backend service for code linting (i.e. analyzing code for issues), with an accompanying &lt;strong&gt;MCP server&lt;/strong&gt; for AI-agent integration.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/mazenaly256/LINTelligent/actions/workflows/ci-pipeline.yml/badge.svg"&gt;&lt;img src="https://github.com/mazenaly256/LINTelligent/actions/workflows/ci-pipeline.yml/badge.svg" alt="CI Pipeline Building and Testing"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Overview&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;A code snippet is submitted in a linting/reviewing request, either as a direct snippet in the request body or via a public GitHub file URL.&lt;/p&gt;
&lt;p&gt;Once the linting request reaches the system, &lt;em&gt;LINTelligent&lt;/em&gt; saves its details in the database and enqueues a background job to the job queue for handling this request, then immediately returns 202 Accepted. If a GitHub URL was provided, the code is first fetched, then the review job runs, otherwise the review job runs directly on the submitted code snippet.&lt;/p&gt;
&lt;p&gt;After that, a worker picks up the job from the job queue and processes it, it fetches the code from the GitHub URL (if exists) then it calls the configured LLM provider with the request details and receive the review report of issues, then updates…&lt;/p&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/mazenaly256/LINTelligent" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;h3&gt;
  
  
  Communication between AI Agent and MCP Server
&lt;/h3&gt;

&lt;p&gt;AI agent (especially the Client) does the MCP handshake via 'initialize' request to get more info about the MCP server and its capabilities then it sends 'tools/list' to know each server's tools, and the same with prompts with 'prompts/list' and resources with 'resources/list' so agent can can invoke those things when it needs. All happening at connection startup, before any actual request for any specific resource, prompt or tool. The actual request happens after that, when LLM decides to use any thing from these available tools during the reasoning loops.&lt;/p&gt;




&lt;h2&gt;
  
  
  Wrap-up
&lt;/h2&gt;

&lt;p&gt;One of the things I learned in this project is what loose coupling really means in practice, I started with a tightly-coupled codebase in the beginning then I had to refactor the whole codebase and architecture to make it testable and write good unit tests.&lt;/p&gt;

&lt;p&gt;I learned many things from this project and shared with you some of them, I hope anyone can learn anything from this blog post or even take a glimpse on something new that can explore more deeply.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mcp</category>
      <category>backend</category>
      <category>api</category>
    </item>
    <item>
      <title>Cinema Seat Reservation System — Part 3: Problems, Decisions and Some Areas Of Improvement</title>
      <dc:creator>Mazen Aly</dc:creator>
      <pubDate>Tue, 14 Jul 2026 09:11:09 +0000</pubDate>
      <link>https://dev.to/mazenaly256/cinema-seat-reservation-system-part-3-problems-decisions-and-some-areas-of-improvement-1n65</link>
      <guid>https://dev.to/mazenaly256/cinema-seat-reservation-system-part-3-problems-decisions-and-some-areas-of-improvement-1n65</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In the two previous parts, I finished sharing my main checkpoints while I was building the system till I deployed it. Today, I need to share two interesting problems that faced me and how I took decisions to solve them. I hope someone can benefit from them.&lt;br&gt;
Also, I will mention the areas of improvement in the system, how it can be better and considering their negative consequences on the system. &lt;em&gt;System design is all about Trade-offs&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;You can find more decisions regarding the system in &lt;code&gt;/docs/decisions/&lt;/code&gt; folder on GitHub repository.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/mazenaly256" rel="noopener noreferrer"&gt;
        mazenaly256
      &lt;/a&gt; / &lt;a href="https://github.com/mazenaly256/Cinema-Seat-Reservation-System" rel="noopener noreferrer"&gt;
        Cinema-Seat-Reservation-System
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Cloud-native microservices-based cinema seat reservation system developed. Designed for modularity and scalability.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Cinema Seat Reservation System&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;em&gt;A cloud-native, microservices-based ecosystem developed in ASP.NET Core with REST APIs. This system features deliberate design decisions optimized for modularity, scalability and resilience — implementing proven distributed systems patterns such as Retries and Circuit Breakers and Request Timeouts alongside automated CI pipelines and manual deployment workflow.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/mazenaly256/Cinema-Seat-Reservation-System/actions/workflows/api-gateway-ci-pipeline.yml/badge.svg"&gt;&lt;img src="https://github.com/mazenaly256/Cinema-Seat-Reservation-System/actions/workflows/api-gateway-ci-pipeline.yml/badge.svg" alt="CI — API Gateway"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer" href="https://github.com/mazenaly256/Cinema-Seat-Reservation-System/actions/workflows/movie-service-ci-pipeline.yml/badge.svg"&gt;&lt;img src="https://github.com/mazenaly256/Cinema-Seat-Reservation-System/actions/workflows/movie-service-ci-pipeline.yml/badge.svg" alt="CI — Movie Service"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer" href="https://github.com/mazenaly256/Cinema-Seat-Reservation-System/actions/workflows/reservation-service-ci-pipeline.yml/badge.svg"&gt;&lt;img src="https://github.com/mazenaly256/Cinema-Seat-Reservation-System/actions/workflows/reservation-service-ci-pipeline.yml/badge.svg" alt="CI — Reservation Service"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer" href="https://github.com/mazenaly256/Cinema-Seat-Reservation-System/actions/workflows/identity-service-ci-pipeline.yml/badge.svg"&gt;&lt;img src="https://github.com/mazenaly256/Cinema-Seat-Reservation-System/actions/workflows/identity-service-ci-pipeline.yml/badge.svg" alt="CI — Identity Service"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Architectural Overview&lt;/h2&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Diagram&lt;/h3&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/mazenaly256/Cinema-Seat-Reservation-System/docs/system-architecture-diagram.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fmazenaly256%2FCinema-Seat-Reservation-System%2FHEAD%2Fdocs%2Fsystem-architecture-diagram.png" alt="System Architecture Diagram"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Services&lt;/h3&gt;

&lt;/div&gt;
&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;th&gt;Responsibility&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;API Gateway&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Centralized authentication, rate limiting, request timeouts, and routing to the main services&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Identity Service&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Centralized Identity Provider — user management and JWT issuance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Movie Service&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Movies and showtimes management&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Reservation Service&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Seat layout, seat holds, and seat reservations&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Getting Started&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;The system is live and ready to test via &lt;strong&gt;&lt;a href="https://www.postman.com/mazenaly256-3830648/workspace/cinema-seat-reservation-system-api-documentation" rel="nofollow noopener noreferrer"&gt;Postman Workspace&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The workspace includes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Complete API documentation, with organized request collections and folders for each service&lt;/li&gt;
&lt;li&gt;All API endpoints with example requests and responses, featuring interactive testing&lt;/li&gt;
&lt;li&gt;Pre-configured variables containing hosting Azure VM IP with ports to access the services&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;How to…&lt;/p&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/mazenaly256/Cinema-Seat-Reservation-System" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;/h2&gt;

&lt;h2&gt;
  
  
  Problems
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Latency Problem
&lt;/h3&gt;

&lt;p&gt;One of the bottlenecks that appeared through load-testing, is that the latency of a specific endpoint (Get all showtimes with filters) takes the latency was around 850ms.&lt;/p&gt;

&lt;h3&gt;
  
  
  Availability Problem
&lt;/h3&gt;

&lt;p&gt;Availability is simply the ability of the system to be alive and respond to requests, and do not completely die.&lt;/p&gt;

&lt;p&gt;Another problem appeared when I tried to stress test the system, I simulated huge traffic on the system and it was across the critical path in the system (that is the longest trip for a request across the services).&lt;br&gt;
Due to the large traffic the service took long time to respond, and also under stress testing the service crashed, due to exceeding the memory that limit that I determined for the container.&lt;/p&gt;

&lt;h2&gt;
  
  
  Furthermore, from a user experience perspective, a service that returns a quick, graceful error is far better than one that hangs indefinitely. Under stress testing, &lt;strong&gt;the P95 latency reached a painful 16 seconds&lt;/strong&gt;, a frustrating experience where users are highly likely to lose patience and abandon their requests entirely.
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Decisions To Solve The Problems
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Solution of Latency Problem
&lt;/h3&gt;

&lt;p&gt;I accepted the idea that the latency has to be slightly high, due to the network overhead that caused by having the database and service running on different servers in different countries so there is a long trip for data over the network between the service and database, but the 850ms latency is also very high even if we consider the network delay, there must be a problem with my system design.&lt;/p&gt;

&lt;p&gt;At first glance, since the problem was related to database reading operations (data retrieval), then database indexing and caching are obvious answers to improve performance and reduce latency, but guess what? Neither of them was the solution in my case.&lt;/p&gt;

&lt;h4&gt;
  
  
  Why indexing did not reduce the latency:
&lt;/h4&gt;

&lt;p&gt;Generally, indexing is a go-to solution in cases like this and I already created a database index on the table, but guess what? There was not any reduction in latency.&lt;br&gt;
What I learned is that due to the high latency, and the  relatively small number of rows (which is ~10,000 rows), the impact of indexing on the latency is invisible especially since the network delay itself was already massive.&lt;/p&gt;

&lt;h4&gt;
  
  
  Why caching is not a solution (common problems in both distributed and in memory):
&lt;/h4&gt;

&lt;p&gt;Actually, I found caching would make things much worse, there are many cons for caching my situation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Range-based queries (from and to date filters) produce highly variable cache keys as if data of 2 days is requested then data of five days that span those two days is requested again, then actually we absolutely need to hit database again as we do not know if there are showtimes in those excess 3 days or not, cache usage rate would be low.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Also full-list caching becomes impractical as the dataset grows to 100k+ rows.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cache invalidation on create/update/delete for the domain resources adds complexity that it actually does not pay off.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those are problems in both in-memory and distributed caching, but even each one has specific cons.&lt;/p&gt;

&lt;p&gt;the main problem with the in-memory caching is in a multi-containered deployment, each container instance maintains its own isolated cache, this produces inconsistent responses, as each container will have its own data separately — unacceptable for a booking system. Furthermore, syncing all those data will add significant complexity.&lt;/p&gt;

&lt;p&gt;also in my case distributed caching (via Redis or any similar) will introduce its own network overhead to transfer data between the service and the Redis instance, that introduce more network delay that will increase latency.&lt;/p&gt;

&lt;h4&gt;
  
  
  The real solution, eliminating unbounded query results
&lt;/h4&gt;

&lt;p&gt;It is pagination, instead of retrieving huge number of rows for a single request, return only a few number of rows like 10 or 20. Practically speaking, users never need more than them, they will see them and if they need more, they can load more and in this case they will accept waiting a few additional milliseconds to see new 10 or 20 showtimes, instead of waiting 850ms to retrieve 10,000 rows that user will never consider them all. &lt;strong&gt;This solution improved the performance reducing the P95 latency to ~515ms, and increased the throughput (the handled traffic) by ~25%&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Theoretically, there is an issue here that may require changing the pagination technique, the issue is that the database still reads every row it skips. Page 5 is fast. Page 5000 is slow. This becomes visible only when the number of becomes really huge.&lt;br&gt;
However, practically speaking, this number of rows will not requested as it require very long date window that contains this enormous number of showtimes, that is not requested in the real life.&lt;/p&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;h3&gt;
  
  
  Solution of the availability problem
&lt;/h3&gt;

&lt;p&gt;To solve this I applied rate limiting on the API gateway, this ensures that any traffic exceeding or limit fails at the edge, guaranteeing that only a manageable number of requests are processed within a given time window.&lt;/p&gt;

&lt;p&gt;Additionally, applying request timeouts helped as it prevented misbehaving requests that are unusually slow for some specific reason from degrading all the system as they take long time to be processed and take some resources. Now the system automatically cancels any request after 8 seconds and disconnect all the related connections and frees up all its allocated resources to be available to another incoming request to consume.&lt;/p&gt;

&lt;p&gt;And prevented the latency from exceeding 8 seconds.&lt;/p&gt;




&lt;h2&gt;
  
  
  Possible Areas of Improvement
&lt;/h2&gt;

&lt;p&gt;In this section I would like to say that honestly, I do not know if these features will actually improve the system, or their effect will be minimal. For sure they will come with their overhead and trade-offs and will require a decision to determine whether they will introduce &lt;em&gt;an actual improvement&lt;/em&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Caching
&lt;/h3&gt;

&lt;p&gt;I discussed the caching when addressing the latency problem and I mentioned why it did not work, but caching may be useful in another part in the system specially when service is read heavy, and also with data that do not change frequently or the data that the way of querying them is consistent (that was not the case in my problem above).&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Event-Driven Architecture and Message Brokers like Kafka and RabbitMQ
&lt;/h3&gt;

&lt;p&gt;At first glance, this solution clearly introduces a major architectural trade-off: &lt;strong&gt;Database Replication&lt;/strong&gt;. On the other hand, it has benefits including that no inter-service network calls are required so the system will be faster, and also no cascading failures, suppose that movie service crashed, the reservation service has all data on its database replica and can actually use and do its work (reserving seats in showtimes) without even knowing that movie service is down.&lt;br&gt;
This will reduce the synchronous HTTP calls that happen frequently between the services in cases like checking movie when adding a new showtime, or checking showtime when trying to reserve a seat. All those are synchronous calls that enforce the upstream service (service that makes a call) to wait for the downstream service (the called service) to respond. Also upstream service fails to do its job if the downstream service goes down.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Change the database location
&lt;/h3&gt;

&lt;p&gt;There are two options to achieve this.&lt;br&gt;
Option A: is to just get a nearer the server for our database. There is no architectural side effects and never presents more challenges, just host the DB on a nearer server to the deployment server of the services, this reduces the travelling distance for data thereby reduce network overhead.&lt;/p&gt;

&lt;p&gt;Option B: is hosting the database on the same machine as the services, this will be actually better in terms of performance due to eliminating the network overhead. But it will introduce its own overhead like the configuration headache and managing the DBMS on the server.&lt;br&gt;
Additionally, it comes with a trade-off, which is &lt;strong&gt;coupling the downtime of DB with the downtime of the system.&lt;/strong&gt; When the services and the database are hosted on different servers, the services can still be available and return friendly errors when the DB server can not be reached, instead of being fully down if they all are on one machine. This is a violation for the principle of &lt;em&gt;single point of failure&lt;/em&gt;, that is "eliminating cascading failures by separating concerns across different machines", but as I said above ad want you to remember: &lt;em&gt;System design is all about Trade-offs&lt;/em&gt;.&lt;/p&gt;

</description>
      <category>redis</category>
      <category>testing</category>
      <category>architecture</category>
      <category>database</category>
    </item>
    <item>
      <title>Cinema Seat Reservation System — Part 2: Transitioning To Production-Scale and Deploying on Azure Cloud</title>
      <dc:creator>Mazen Aly</dc:creator>
      <pubDate>Wed, 24 Jun 2026 06:26:12 +0000</pubDate>
      <link>https://dev.to/mazenaly256/cinema-seat-reservation-system-from-baseline-local-development-to-live-cloud-native-production--238k</link>
      <guid>https://dev.to/mazenaly256/cinema-seat-reservation-system-from-baseline-local-development-to-live-cloud-native-production--238k</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;This is the second part of sharing my journey to create a microservices-based backend system, in the previous part, I introduced the system and its services.&lt;br&gt;
In this part I am going to mention the main things that happened with me from then until now.&lt;/p&gt;




&lt;h2&gt;
  
  
  Transitioning to online DBaaS platforms
&lt;/h2&gt;

&lt;p&gt;The first main thing was to transition my databases from my local device to accessible over the internet. I used &lt;strong&gt;Neon&lt;/strong&gt; and &lt;strong&gt;MongoDB Atlas&lt;/strong&gt;. Although performance-wise it is better to deploy the database on the same server that the whole system so all services can access the databases without &lt;strong&gt;network overhead&lt;/strong&gt;, This solution is better from a point, that is avoiding consuming the free VM instance that I got to host my main services, as with DBaaS platforms I will not require storage for databases or additional overhead to handle the DBMS on a free small resources-constrained VM.&lt;/p&gt;




&lt;h2&gt;
  
  
  Observability
&lt;/h2&gt;

&lt;p&gt;Observability is one of the main concerns in any system, it gives the ability for the system to expose what happens inside it without any need to guess and manually trace the code to determine where the error may happened.&lt;br&gt;
I utilized &lt;strong&gt;OpenTelemetry&lt;/strong&gt;, as I found it is most used and accepted tool to log, trace and collect metrics about the system and the traffic. Also, I loved that it is not related to specific framework, that is .NET by the way, I loved the idea that it is standalone tool.&lt;br&gt;
But logging and tracing and metrics collection will not be beneficial if we do not see it actually and can achieve &lt;strong&gt;monitoring&lt;/strong&gt; from those telemetry data, so I used &lt;strong&gt;Grafana Cloud&lt;/strong&gt; to export the telemetry data to some place that is accessible online and a tool that can generate dashboards and visualizing for the metrics (&lt;strong&gt;Prometheus&lt;/strong&gt;), and UI that can show all the telemetry data easily.&lt;/p&gt;




&lt;h2&gt;
  
  
  Resilience
&lt;/h2&gt;

&lt;p&gt;I achieved &lt;em&gt;resilience&lt;/em&gt; in this system, by implementing Retry and Circuit-Breaker Pattern, that applies retires and mitigates the effect transient failures, so user can not know that there is actually a failure happened.&lt;br&gt;
Without it, any HTTP transient failure when calling a downstream service will lead to Internal Server Error response directly, even there is no permanent failure in the downstream service.&lt;/p&gt;




&lt;h2&gt;
  
  
  Deployment
&lt;/h2&gt;

&lt;p&gt;Until this point, we have a system that is fully functional and have consistent docker configuration for its services via Docker Compose, and it database is already there and available.&lt;/p&gt;

&lt;p&gt;Now this is the point at which I wanted my system to be online and accessible from everywhere over the world, and really reach the goal: From Baseline Local Development &lt;strong&gt;To Live Cloud-Native Production&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For this I chose Azure Cloud Services, I had a virtual machine on Azure Cloud and installed Docker on it, also I configured the firewall so it added two ports to access my system, one for Identity Service, and the another one is for API Gateway.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I did is as follows:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;I created images from my actual code on my local machine, and pushed it to GitHub Container Registry.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I issued a token from GitHub to allow Docker engine that is installed on the virtual machine to actually pull and push the images (it is called Packages of type containers on GitHub) from and to my GitHub account.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I copied (via SCP) Docker Compose file with secret env variables file, from my local machine to the online Azure VM. Now the VM has Docker engine, and the ability to access any uploaded images on GitHub and pull/download them on the VM.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Finally, I executed the command: &lt;code&gt;docker compose pull&lt;/code&gt; to pull images from GitHub Container Registry then &lt;code&gt;docker compose up&lt;/code&gt;  and to spin up the containers from them.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Voilà! the system became live and accessible online.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And now, we have a live production-scale cloud-native application.&lt;/p&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://github.com/mazenaly256/Cinema-Seat-Reservation-System/releases/tag/v4.0.0" rel="noopener noreferrer"&gt;See GitHub Release, Capturing Project at This Point&lt;/a&gt;
&lt;/h3&gt;




&lt;h2&gt;
  
  
  Workflow
&lt;/h2&gt;

&lt;p&gt;After I had this whole setup, my workflow became very consistent, it is as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Make a change in the code, fixing a bug or enhance codebase or add a feature, then push it to GitHub, every change should be pushed to GitHub to achieve CI (continuous integration) practice in software development, that is simply the practice of merging the new code changes to the branch and then get automatically tested and checked, and this is achieved by the &lt;strong&gt;CI Pipeline&lt;/strong&gt; that I built using &lt;strong&gt;GitHub Actions&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Then I directly rebuild the images so I get the latest changes on the code reflected on the new images.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I push these latest versions of images to GitHub Online Registry.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I access the VM through SSH, delete the old &lt;code&gt;docker-compose.yml&lt;/code&gt; and &lt;code&gt;.env&lt;/code&gt; files if they are modified.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rerun the docker compose commands to pull the latest images from GitHub Container Registry and spin up new containers and delete the old containers. So, CD (Continuous Deployment/Delivery) is achieved here (manual CD workflow).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In conclusion, I want to say that this project made me learn many valuable skills, concepts and tools. There are many another things that not mentioned to keep things brief (you can get some of them by taking a look on GitHub Repository that is mentioned in Part 1 from this series, and view the commits history), and focus on the points that I feel that it really matters and think that readers can learn from it.&lt;/p&gt;

&lt;p&gt;Take a look on this series title, we really transitioned from &lt;em&gt;"Baseline Local Development"&lt;/em&gt; that is the MVP that runs on my machine, to &lt;em&gt;"Live Cloud-Native Production"&lt;/em&gt; that actually appeared in observability setup and deploying on Cloud and making it accessible online.&lt;/p&gt;

&lt;p&gt;&lt;u&gt;If you have questions or feedback, drop them in the comments. I hope I can learn from or add benefit to one of you&lt;/u&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;p&gt;For now, I am testing the system to determine its bottlenecks, for sure it has many areas of improvement, and things that even can be added to this project to make it better and more performant, I am going to mention some bugs and issues that faced me and how I overcame it and learned from them and some decisions that I made in the system. This what I will mention in the next part "Bugs, Decisions and Areas Of Improvement".&lt;/p&gt;

</description>
      <category>cloud</category>
      <category>azure</category>
      <category>distributedsystems</category>
      <category>microservices</category>
    </item>
    <item>
      <title>Cinema Seat Reservation System — Part 1: Overview &amp; Architecture</title>
      <dc:creator>Mazen Aly</dc:creator>
      <pubDate>Tue, 26 May 2026 08:11:09 +0000</pubDate>
      <link>https://dev.to/mazenaly256/cinema-seat-reservation-system-from-baseline-local-development-to-live-cloud-native-production--1d9i</link>
      <guid>https://dev.to/mazenaly256/cinema-seat-reservation-system-from-baseline-local-development-to-live-cloud-native-production--1d9i</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;I am writing this series of blog posts to document what I am learning while building a project. You are welcome to criticize and guide me toward areas of improvement — or maybe, and I genuinely hope this, I can introduce you to concepts or ideas you haven’t encountered before, so we both can grow. I will focus on architectural and design concepts and the technologies that can be applied regardless of your framework and programming language of developing the application.&lt;/p&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;h3&gt;
  
  
  GitHub Repository
&lt;/h3&gt;

&lt;p&gt;There you can find more details, including ADRs (Architectural Design Records) and more extensive documentation.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/mazenaly256" rel="noopener noreferrer"&gt;
        mazenaly256
      &lt;/a&gt; / &lt;a href="https://github.com/mazenaly256/Cinema-Seat-Reservation-System" rel="noopener noreferrer"&gt;
        Cinema-Seat-Reservation-System
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Cloud-native microservices-based cinema seat reservation system developed in ASP.NET with REST API, featuring deliberate system design decisions. Designed for modularity and scalability.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Cinema Seat Reservation System&lt;/h1&gt;

&lt;/div&gt;
&lt;p&gt;&lt;em&gt;A cloud-native, microservices-based ecosystem developed in ASP.NET Core with REST APIs. This system features deliberate design decisions optimized for modularity, scalability and resilience — implementing proven distributed systems patterns such as Retries and Circuit Breakers and Request Timeouts alongside automated CI/CD pipelines.&lt;/em&gt;&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Architectural Overview&lt;/h2&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Diagram&lt;/h3&gt;

&lt;/div&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/mazenaly256/Cinema-Seat-Reservation-System/docs/system-architecture-diagram.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fmazenaly256%2FCinema-Seat-Reservation-System%2FHEAD%2Fdocs%2Fsystem-architecture-diagram.png" alt="System Architecture Diagram"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Services&lt;/h3&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Movie Service:&lt;/strong&gt; Responsible for movies and showtimes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reservation Service:&lt;/strong&gt; Responsible for seats layout representation and seat reservation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Identity Service:&lt;/strong&gt; Acts as the centralized Identity Provider (IdP) for the system.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API Gateway:&lt;/strong&gt; Centralizes the logic of authentication and applies rate limiting, timeouts, and routing policies for all incoming traffic.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;API Documentation&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;&lt;a href="https://www.postman.com/mazenaly256-3830648/workspace/cinema-seat-reservation-system-api-documentation" rel="nofollow noopener noreferrer"&gt;Postman API Workspace&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/mazenaly256/Cinema-Seat-Reservation-System" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;





&lt;h2&gt;
  
  
  System Overview
&lt;/h2&gt;

&lt;p&gt;I have built a &lt;strong&gt;microservices-based&lt;/strong&gt; backend system, for handling seat reservations in a cinema, each service has its &lt;strong&gt;own database&lt;/strong&gt;. I applied many new concepts that I have learned including how to split the system and build the architecture that offers the modularity and future scalability for the application, building and securing API endpoints using JWT, implementing an &lt;strong&gt;API gateway&lt;/strong&gt; to be the single entry point for my whole system, &lt;strong&gt;building a basic CI Pipeline using GitHub Actions&lt;/strong&gt;, containerizing the services with configuring and running together via &lt;strong&gt;Docker Compose&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;h3&gt;
  
  
  Services
&lt;/h3&gt;

&lt;p&gt;&lt;u&gt;Movie Service:&lt;/u&gt; Responsible for CRUD operations on movies and showtimes, and enforces role-based access control.&lt;/p&gt;

&lt;p&gt;&lt;u&gt;Reservation Service:&lt;/u&gt; Responsible for handling seats availability checks and the logic of seats reservations and payment.&lt;/p&gt;

&lt;p&gt;&lt;u&gt;Identity Service:&lt;/u&gt; Acts as the &lt;strong&gt;centralized Identity Provider&lt;/strong&gt; for the whole system, responsible for &lt;strong&gt;storing and managing users&lt;/strong&gt; and &lt;strong&gt;issuing JWT tokens&lt;/strong&gt; that are trusted across all the system.&lt;/p&gt;

&lt;p&gt;&lt;u&gt;API Gateway:&lt;/u&gt; The single entry point for the system, acting as an &lt;strong&gt;architectural AOP (Aspect-Oriented Programming) layer&lt;/strong&gt;. It &lt;strong&gt;centralizes cross-cutting concerns&lt;/strong&gt; like authentication, rate limiting, and request timeouts in one place instead of duplicating their logic across all the system services. In addition to the main responsibility of API Gateway that is &lt;strong&gt;forwarding the requests to downstream services&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;h3&gt;
  
  
  System Architecture
&lt;/h3&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%2F4j4liw4f8axc0chel2mg.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%2F4j4liw4f8axc0chel2mg.png" alt="Basic System Architecture Diagram" width="800" height="604"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://github.com/mazenaly256/Cinema-Seat-Reservation-System/releases/tag/v3.0.0" rel="noopener noreferrer"&gt;GitHub Release&lt;/a&gt;
&lt;/h3&gt;




&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;p&gt;What I am going to do in my next few posts, is to document the main points of transitioning this system from the &lt;strong&gt;development phase on my local machine&lt;/strong&gt; to a &lt;strong&gt;fully deployed, cloud-native, production-scale system&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>softwareengineering</category>
      <category>architecture</category>
      <category>backend</category>
    </item>
  </channel>
</rss>
