<?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>Forem: Mohamed Azmy</title>
    <description>The latest articles on Forem by Mohamed Azmy (@azmy).</description>
    <link>https://forem.com/azmy</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%2F2588253%2Fcc6912f8-7d6d-4661-b96d-5958a7213982.jpg</url>
      <title>Forem: Mohamed Azmy</title>
      <link>https://forem.com/azmy</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/azmy"/>
    <language>en</language>
    <item>
      <title>Publish Subscribe Model</title>
      <dc:creator>Mohamed Azmy</dc:creator>
      <pubDate>Sun, 22 Feb 2026 16:35:02 +0000</pubDate>
      <link>https://forem.com/azmy/publish-subscribe-model-490j</link>
      <guid>https://forem.com/azmy/publish-subscribe-model-490j</guid>
      <description>&lt;p&gt;

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


&lt;/p&gt;

&lt;p&gt; A notification system is responsible for sending alerts to users, such as breaking news, product updates, event reminders, and promotions. Notifications are not limited to mobile push messages. In practice, there are three major notification channels: push notifications, SMS messages, and emails. &lt;/p&gt;



&lt;h2&gt;Defining the Scope and Requirements&lt;/h2&gt;

&lt;p&gt; Before designing a notification system, we must first understand the problem and clarify the system requirements. System design problems are often open-ended, so asking the right questions is essential. &lt;/p&gt;

&lt;p&gt; Key requirements include: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What types of notifications are supported?&lt;/li&gt;
&lt;li&gt;Is the system real-time?&lt;/li&gt;
&lt;li&gt;Which devices should receive notifications?&lt;/li&gt;
&lt;li&gt;What triggers notifications?&lt;/li&gt;
&lt;li&gt;Can users opt out?&lt;/li&gt;
&lt;li&gt;What is the expected scale?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; In our design, the system supports push notifications, SMS, and email. Notifications should be delivered as quickly as possible, with small delays acceptable under heavy load. &lt;/p&gt;

&lt;p&gt; The system must work across iOS devices, Android devices, and desktop or laptop computers. &lt;/p&gt;

&lt;p&gt; Notifications can be triggered by user actions through client applications, or by server-side scheduled jobs such as reminders and marketing campaigns. &lt;/p&gt;

&lt;p&gt; Users must also be able to opt out, and the system must respect their notification preferences. &lt;/p&gt;

&lt;p&gt; At scale, the system sends around 10 million push notifications, 1 million SMS messages, and 5 million emails every day. &lt;/p&gt;

&lt;p&gt; This makes it a large-scale system that must be fast, reliable, scalable, and support multiple delivery channels. &lt;/p&gt;



&lt;h2&gt;High-Level Notification System Architecture&lt;/h2&gt;

&lt;p&gt; At a high level, services in our system do not communicate directly with external providers like Apple or Google. Instead, they send requests to a centralized Notification Service API. &lt;/p&gt;

&lt;p&gt; This notification service determines the type of message — push, SMS, or email — builds the correct payload, and routes it through the appropriate delivery channel. &lt;/p&gt;

&lt;p&gt; Finally, third-party providers handle the actual delivery to user devices. &lt;/p&gt;



&lt;h2&gt;Notification Delivery Channels&lt;/h2&gt;

&lt;p&gt; A modern notification system must support multiple channels, each with its own external provider. &lt;/p&gt;

&lt;h3&gt;iOS Push Notifications (APNs)&lt;/h3&gt;

&lt;p&gt; For iOS push notifications, the flow includes three components: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Provider: our server that builds the notification request&lt;/li&gt;
&lt;li&gt;APNs: Apple Push Notification Service that delivers the message&lt;/li&gt;
&lt;li&gt;iOS Device: the client that receives and displays the alert&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; The provider requires: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A device token (unique identifier for the iPhone)&lt;/li&gt;
&lt;li&gt;A payload (JSON containing the title, body, and metadata)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Android Push Notifications (FCM)&lt;/h3&gt;

&lt;p&gt; Android push notifications follow a similar flow, except that Firebase Cloud Messaging (FCM) is used instead of APNs. &lt;/p&gt;

&lt;h3&gt;SMS Notifications&lt;/h3&gt;

&lt;p&gt; SMS messages are typically delivered through third-party providers such as Twilio or Nexmo, rather than being sent directly from internal servers. &lt;/p&gt;

&lt;h3&gt;Email Notifications&lt;/h3&gt;

&lt;p&gt; Most companies rely on third-party email services like SendGrid or Mailchimp due to their high delivery rates, reliability, and analytics support. &lt;/p&gt;



&lt;h2&gt;Collecting User Contact Information&lt;/h2&gt;

&lt;p&gt; To send notifications, the system must store the user’s contact details. When a user signs up or installs the application, our API servers collect this information and store it in the database. &lt;/p&gt;

&lt;p&gt; Typical stored data includes: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Device tokens for push notifications&lt;/li&gt;
&lt;li&gt;Phone numbers for SMS&lt;/li&gt;
&lt;li&gt;Email addresses for email delivery&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; A simple database structure includes: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;User Table: profile information, email, phone number&lt;/li&gt;
&lt;li&gt;Device Table: device tokens linked to the user (supporting multiple devices per user)&lt;/li&gt;
&lt;/ul&gt;



&lt;h2&gt;Core System Components&lt;/h2&gt;

&lt;p&gt; The key building blocks of the notification architecture include: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Services that trigger notifications (microservices, cron jobs, distributed systems)&lt;/li&gt;
&lt;li&gt;A central Notification System that receives requests and builds payloads&lt;/li&gt;
&lt;li&gt;Third-party providers responsible for delivering notifications&lt;/li&gt;
&lt;li&gt;User devices that ultimately receive the alerts&lt;/li&gt;
&lt;/ul&gt;



&lt;h2&gt;Third-Party Provider Considerations&lt;/h2&gt;

&lt;p&gt; Integrating external providers introduces two important requirements: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Extensibility: adding or replacing providers should require minimal changes&lt;/li&gt;
&lt;li&gt;Provider Availability: some providers may not work in certain regions (e.g., FCM in China), requiring alternatives like JPush&lt;/li&gt;
&lt;/ul&gt;



&lt;h2&gt;Problems with the Initial Single-Server Design&lt;/h2&gt;

&lt;p&gt; A simple architecture with only one notification server leads to three major challenges: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Single Point of Failure: if the server fails, all notifications stop&lt;/li&gt;
&lt;li&gt;Hard to Scale: individual components cannot scale independently&lt;/li&gt;
&lt;li&gt;Performance Bottlenecks: slow tasks and API delays can overwhelm the system&lt;/li&gt;
&lt;/ul&gt;



&lt;h2&gt;Improving Scalability and Reliability&lt;/h2&gt;

&lt;p&gt; To evolve the design into a production-ready system, we introduce three key improvements: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Separate the database and cache into independent services for better scalability&lt;/li&gt;
&lt;li&gt;Add multiple notification servers behind a load balancer for horizontal scaling&lt;/li&gt;
&lt;li&gt;Introduce message queues to decouple components and enable asynchronous processing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; With message queues, services simply enqueue notification jobs, and worker servers process them asynchronously. This removes bottlenecks, improves resilience, and supports high traffic efficiently. &lt;/p&gt;



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

&lt;p&gt; By combining multiple delivery channels, scalable infrastructure, and asynchronous message queues, we can build a modern notification system that is reliable, extensible, and capable of handling millions of notifications per day. &lt;/p&gt;

</description>
      <category>webdev</category>
      <category>backend</category>
      <category>systemdesign</category>
      <category>realtime</category>
    </item>
    <item>
      <title>Notification System Design</title>
      <dc:creator>Mohamed Azmy</dc:creator>
      <pubDate>Sat, 07 Feb 2026 17:25:17 +0000</pubDate>
      <link>https://forem.com/azmy/notification-system-design-12ol</link>
      <guid>https://forem.com/azmy/notification-system-design-12ol</guid>
      <description>&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/oKjk-a8FEGE"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;

&lt;p&gt; A notification system is responsible for sending alerts to users, such as breaking news, product updates, event reminders, and promotions. &lt;/p&gt; &lt;p&gt; Notifications are not limited to mobile push messages. In practice, there are three major notification channels: push notifications, SMS messages, and emails. &lt;/p&gt; &lt;br&gt; &lt;h2&gt;Defining the Scope and Requirements&lt;/h2&gt; &lt;p&gt; Before designing a notification system, we must first understand the problem and clarify the system requirements. System design problems are often open-ended, so asking the right questions is essential. &lt;/p&gt; &lt;p&gt; Key requirements include: &lt;/p&gt; &lt;p&gt; • What types of notifications are supported?&lt;br&gt; • Is the system real-time?&lt;br&gt; • Which devices should receive notifications?&lt;br&gt; • What triggers notifications?&lt;br&gt; • Can users opt out?&lt;br&gt; • What is the expected scale?&lt;br&gt; &lt;/p&gt; &lt;p&gt; In our design, the system supports push notifications, SMS, and email. Notifications should be delivered as quickly as possible, with small delays acceptable under heavy load. &lt;/p&gt; &lt;p&gt; The system must work across iOS devices, Android devices, and desktop or laptop computers. &lt;/p&gt; &lt;p&gt; Notifications can be triggered by user actions through client applications, or by server-side scheduled jobs such as reminders and marketing campaigns. &lt;/p&gt; &lt;p&gt; Users must also be able to opt out, and the system must respect their notification preferences. &lt;/p&gt; &lt;p&gt; At scale, the system sends around 10 million push notifications, 1 million SMS messages, and 5 million emails every day. &lt;/p&gt; &lt;p&gt; This makes it a large-scale system that must be fast, reliable, scalable, and support multiple delivery channels. &lt;/p&gt; &lt;br&gt; &lt;h2&gt;High-Level Notification System Architecture&lt;/h2&gt; &lt;p&gt; At a high level, services in our system do not communicate directly with external providers like Apple or Google. Instead, they send requests to a centralized Notification Service API. &lt;/p&gt; &lt;p&gt; This notification service determines the type of message — push, SMS, or email — builds the correct payload, and routes it through the appropriate delivery channel. &lt;/p&gt; &lt;p&gt; Finally, third-party providers handle the actual delivery to user devices. &lt;/p&gt; &lt;br&gt; &lt;h2&gt;Notification Delivery Channels&lt;/h2&gt; &lt;p&gt; A modern notification system must support multiple channels, each with its own external provider. &lt;/p&gt; &lt;br&gt; &lt;h2&gt;iOS Push Notifications (APNs)&lt;/h2&gt; &lt;p&gt; For iOS push notifications, the flow includes three components: &lt;/p&gt; &lt;p&gt; • Provider: our server that builds the notification request&lt;br&gt; • APNs: Apple Push Notification Service that delivers the message&lt;br&gt; • iOS Device: the client that receives and displays the alert&lt;br&gt; &lt;/p&gt; &lt;p&gt; The provider requires: &lt;/p&gt; &lt;p&gt; • A device token (unique identifier for the iPhone)&lt;br&gt; • A payload (JSON containing the title, body, and metadata)&lt;br&gt; &lt;/p&gt; &lt;br&gt; &lt;h2&gt;Android Push Notifications (FCM)&lt;/h2&gt; &lt;p&gt; Android push notifications follow a similar flow, except that Firebase Cloud Messaging (FCM) is used instead of APNs. &lt;/p&gt; &lt;br&gt; &lt;h2&gt;SMS Notifications&lt;/h2&gt; &lt;p&gt; SMS messages are typically delivered through third-party providers such as Twilio or Nexmo, rather than being sent directly from internal servers. &lt;/p&gt; &lt;br&gt; &lt;h2&gt;Email Notifications&lt;/h2&gt; &lt;p&gt; Most companies rely on third-party email services like SendGrid or Mailchimp due to their high delivery rates, reliability, and analytics support. &lt;/p&gt; &lt;br&gt; &lt;h2&gt;Collecting User Contact Information&lt;/h2&gt; &lt;p&gt; To send notifications, the system must store the user’s contact details. When a user signs up or installs the application, our API servers collect this information and store it in the database. &lt;/p&gt; &lt;p&gt; Typical stored data includes: &lt;/p&gt; &lt;p&gt; • Device tokens for push notifications&lt;br&gt; • Phone numbers for SMS&lt;br&gt; • Email addresses for email delivery&lt;br&gt; &lt;/p&gt; &lt;p&gt; A simple database structure includes: &lt;/p&gt; &lt;p&gt; • User Table: profile information, email, phone number&lt;br&gt; • Device Table: device tokens linked to the user (supporting multiple devices per user)&lt;br&gt; &lt;/p&gt; &lt;br&gt; &lt;h2&gt;Core System Components&lt;/h2&gt; &lt;p&gt; The key building blocks of the notification architecture include: &lt;/p&gt; &lt;p&gt; • Services that trigger notifications (microservices, cron jobs, distributed systems)&lt;br&gt; • A central Notification System that receives requests and builds payloads&lt;br&gt; • Third-party providers responsible for delivering notifications&lt;br&gt; • User devices that ultimately receive the alerts&lt;br&gt; &lt;/p&gt; &lt;br&gt; &lt;h2&gt;Third-Party Provider Considerations&lt;/h2&gt; &lt;p&gt; Integrating external providers introduces two important requirements: &lt;/p&gt; &lt;p&gt; • Extensibility: adding or replacing providers should require minimal changes&lt;br&gt; • Provider Availability: some providers may not work in certain regions (e.g., FCM in China), requiring alternatives like JPush&lt;br&gt; &lt;/p&gt; &lt;br&gt; &lt;h2&gt;Problems with the Initial Single-Server Design&lt;/h2&gt; &lt;p&gt; A simple architecture with only one notification server leads to three major challenges: &lt;/p&gt; &lt;p&gt; • Single Point of Failure: if the server fails, all notifications stop&lt;br&gt; • Hard to Scale: individual components cannot scale independently&lt;br&gt; • Performance Bottlenecks: slow tasks and API delays can overwhelm the system&lt;br&gt; &lt;/p&gt; &lt;br&gt; &lt;h2&gt;Improving Scalability and Reliability&lt;/h2&gt; &lt;p&gt; To evolve the design into a production-ready system, we introduce three key improvements: &lt;/p&gt; &lt;p&gt; • Separate the database and cache into independent services for better scalability&lt;br&gt; • Add multiple notification servers behind a load balancer for horizontal scaling&lt;br&gt; • Introduce message queues to decouple components and enable asynchronous processing&lt;br&gt; &lt;/p&gt; &lt;p&gt; With message queues, services simply enqueue notification jobs, and worker servers process them asynchronously. This removes bottlenecks, improves resilience, and supports high traffic efficiently. &lt;/p&gt; &lt;br&gt; &lt;h2&gt;Conclusion&lt;/h2&gt; &lt;p&gt; By combining multiple delivery channels, scalable infrastructure, and asynchronous message queues, we can build a modern notification system that is reliable, extensible, and capable of handling millions of notifications per day. &lt;/p&gt;

</description>
      <category>webdev</category>
      <category>backend</category>
      <category>systemdesign</category>
      <category>realtime</category>
    </item>
    <item>
      <title>HTTP Push Mechanism</title>
      <dc:creator>Mohamed Azmy</dc:creator>
      <pubDate>Sat, 31 Jan 2026 09:49:49 +0000</pubDate>
      <link>https://forem.com/azmy/http-push-mechanism-3c3j</link>
      <guid>https://forem.com/azmy/http-push-mechanism-3c3j</guid>
      <description>&lt;p&gt;

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


&lt;/p&gt;

&lt;p&gt; Modern web applications increasingly rely on real-time communication. Whether it's live notifications, collaborative tools, or multiplayer games, waiting for the client to ask for updates is often not good enough. This is where HTTP Push and persistent connections come into play. &lt;/p&gt; &lt;p&gt; In this article, we’ll explore: &lt;/p&gt; &lt;p&gt; • How traditional HTTP Pull works&lt;br&gt; • The role of Time To Live (TTL)&lt;br&gt; • Persistent connections and heartbeat mechanisms&lt;br&gt; • Why HTTP Push can be resource-intensive&lt;br&gt; • Common technologies used to implement it &lt;/p&gt; &lt;br&gt; &lt;h2&gt;The Traditional HTTP Pull Model&lt;/h2&gt; &lt;p&gt; By default, web communication follows the HTTP Pull model: &lt;/p&gt; &lt;p&gt; • The client sends a request&lt;br&gt; • The server processes it&lt;br&gt; • The server returns a response&lt;br&gt; • The connection is closed &lt;/p&gt; &lt;p&gt; Each request has a Time To Live (TTL), typically between 30 and 60 seconds, depending on the browser and environment. &lt;/p&gt; &lt;p&gt; If the server does not respond within this time window, the browser assumes the request has stalled and closes the connection. The client must then send a new request to try again. &lt;/p&gt; &lt;p&gt; This behavior is intentional. Open connections consume server resources such as memory and file descriptors, and servers can only handle a limited number of simultaneous connections. Without a timeout mechanism, a server could eventually exhaust its resources. &lt;/p&gt; &lt;br&gt; &lt;h2&gt;When HTTP Pull Is Not Enough&lt;/h2&gt; &lt;p&gt; The HTTP Pull model works well for most use cases, but it breaks down in scenarios where: &lt;/p&gt; &lt;p&gt; • The server response takes longer than the TTL&lt;br&gt; • The server needs to send data as soon as it becomes available&lt;br&gt; • Low-latency, real-time updates are required &lt;/p&gt; &lt;p&gt; In these cases, repeatedly polling the server is inefficient and introduces unnecessary delays. &lt;/p&gt; &lt;br&gt; &lt;h2&gt;Persistent Connections and HTTP Push&lt;/h2&gt; &lt;p&gt; To solve this, we use persistent connections. &lt;/p&gt; &lt;p&gt; A persistent connection remains open between the client and the server instead of closing after a single request-response cycle. Once established, the server can push data to the client whenever it is ready, without waiting for a new request. &lt;/p&gt; &lt;p&gt; This communication pattern is commonly referred to as HTTP Push and forms the foundation of many real-time web systems. &lt;/p&gt; &lt;br&gt; &lt;h2&gt;Keeping the Connection Alive: Heartbeat Interceptors&lt;/h2&gt; &lt;p&gt; Browsers are designed to close idle connections. To prevent this from happening, persistent connections rely on heartbeat mechanisms. &lt;/p&gt; &lt;p&gt; Heartbeats are small, lightweight messages exchanged periodically between the client and the server. They usually contain no meaningful data. Their sole purpose is to signal that the connection is still active and should not be terminated due to inactivity. &lt;/p&gt; &lt;p&gt; Without heartbeats, browsers or proxies would close long-lived connections, making HTTP Push unreliable. &lt;/p&gt; &lt;br&gt; &lt;h2&gt;The Cost of Persistent Connections&lt;/h2&gt; &lt;p&gt; While powerful, persistent connections come with trade-offs. &lt;/p&gt; &lt;p&gt; Compared to traditional HTTP Pull: &lt;/p&gt; &lt;p&gt; • They consume more memory per client&lt;br&gt; • They require more careful connection management&lt;br&gt; • They increase server complexity &lt;/p&gt; &lt;p&gt; Because each client holds an open connection, scalability becomes a critical concern. This is why HTTP Push should be used only when real-time communication is truly required. &lt;/p&gt; &lt;br&gt; &lt;h2&gt;Real-World Use Case: Multiplayer Browser Games&lt;/h2&gt; &lt;p&gt; A clear example where HTTP Push is essential is browser-based multiplayer games. &lt;/p&gt; &lt;p&gt; Players need to receive continuous, real-time updates about game state, actions, and events. Polling the server every few seconds would result in poor responsiveness and a degraded user experience. &lt;/p&gt; &lt;p&gt; In this scenario, maintaining a persistent connection dramatically improves performance and responsiveness. &lt;/p&gt; &lt;br&gt; &lt;h2&gt;Common Technologies for HTTP Push&lt;/h2&gt; &lt;p&gt; Several technologies are commonly used to implement long-lived connections: &lt;/p&gt; &lt;p&gt; • Ajax Long Polling – Simulates push by keeping requests open until data is available&lt;br&gt; • WebSockets – Provides full-duplex, real-time communication over a single persistent connection&lt;br&gt; • Server-Sent Events (SSE) – Allows servers to push one-way updates to clients over HTTP &lt;/p&gt; &lt;p&gt; Each approach has its own strengths and trade-offs, and the right choice depends on the application’s requirements. &lt;/p&gt; &lt;br&gt; &lt;h2&gt;Conclusion&lt;/h2&gt; &lt;p&gt; HTTP Push enables real-time communication by keeping connections open and allowing servers to send data as soon as it’s available. While this approach is more resource-intensive than traditional HTTP Pull, it is indispensable for modern applications that demand low latency and real-time updates. &lt;/p&gt; &lt;p&gt; Understanding how TTL, persistent connections, and heartbeat mechanisms work together helps engineers design systems that are both responsive and scalable. &lt;/p&gt; &lt;p&gt; When used thoughtfully, HTTP Push can significantly enhance the user experience in modern web applications. &lt;/p&gt;

</description>
      <category>webdev</category>
      <category>backend</category>
      <category>systemdesign</category>
      <category>realtime</category>
    </item>
    <item>
      <title>Linux: The Secret Weapon for Developers</title>
      <dc:creator>Mohamed Azmy</dc:creator>
      <pubDate>Tue, 06 Jan 2026 17:54:03 +0000</pubDate>
      <link>https://forem.com/azmy/linux-the-secret-weapon-for-developers-18ml</link>
      <guid>https://forem.com/azmy/linux-the-secret-weapon-for-developers-18ml</guid>
      <description>&lt;p&gt;Linux is an operating system like Windows and macOS, but for a long time it was mostly associated with servers and enterprise environments. Early Linux distributions were powerful but not very user-friendly, mainly because of complex interfaces and setup processes. Over the years, developers around the world have continuously improved Linux, making it easier to use, more polished, and more accessible.&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;
Today, Linux is everywhere. It runs on personal laptops, home desktops, cloud platforms, enterprise servers, cars, smart devices, and critical infrastructure. This widespread adoption is not accidental — Linux offers several advantages that make it especially attractive to programmers and developers.
&lt;/p&gt;

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

&lt;p&gt;
The short video below highlights why many developers consider Linux their secret weapon. It gives a fast visual breakdown of the key reasons programmers prefer Linux for development work.
&lt;/p&gt;

&lt;h2&gt;Why Programmers Choose Linux&lt;/h2&gt;

&lt;p&gt;
One of the biggest reasons programmers choose Linux is security. Linux is built around a strong permission model that separates regular users from administrative access. Most system-level changes require root privileges, which makes it much harder for viruses and malware to cause serious damage. This design also improves privacy, since Linux does not constantly collect or upload user data in the background.
&lt;/p&gt;

&lt;p&gt;
Customization is another major advantage. Linux allows developers to fully control how their system looks and behaves. Users can choose from different desktop environments, customize themes, icons, fonts, and system tools, and create workflows that perfectly match their needs. Shell scripting makes it easy to automate tasks and improve productivity.
&lt;/p&gt;

&lt;p&gt;
Linux is also extremely efficient with hardware resources. Unlike many modern operating systems that slow down older machines, Linux can run smoothly on low-end or outdated hardware. It uses CPU and memory efficiently, making it an excellent choice for development machines, servers, and embedded systems.
&lt;/p&gt;

&lt;p&gt;
Automation plays a huge role in Linux-based workflows. Developers can write bash scripts to automate repetitive tasks such as file management, backups, data processing, deployments, and system maintenance. This saves time, reduces errors, and allows programmers to focus on building software instead of managing systems.
&lt;/p&gt;

&lt;p&gt;
Another strong point is the Linux community. Millions of developers around the world actively contribute to forums, documentation, and open-source projects. If you encounter a problem, chances are someone else has already faced it and shared a solution. For enterprises, professional support is also available from companies like Red Hat and Canonical.
&lt;/p&gt;

&lt;p&gt;
Linux is known for its stability and reliability. Many Linux systems run for months or even years without needing a reboot. This is why most servers, cloud platforms, and data centers rely on Linux. Updates usually do not interrupt running services, which helps reduce downtime and operational costs.
&lt;/p&gt;

&lt;p&gt;
Finally, Linux is open source. Anyone can view, modify, and improve the source code without paying license fees. This freedom allows developers, companies, and even entire countries to build custom Linux systems that fit their needs while keeping costs low and control high.
&lt;/p&gt;

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

&lt;p&gt;
Linux has evolved from a server-only operating system into a powerful, flexible, and reliable platform for developers. With strong security, deep customization, efficient performance, automation capabilities, community support, and open-source freedom, Linux continues to be a secret weapon for programmers around the world.
&lt;/p&gt;

</description>
      <category>linux</category>
      <category>backend</category>
      <category>devops</category>
      <category>ai</category>
    </item>
    <item>
      <title>Understanding Coupling: Afferent vs Efferent Dependencies in System Design</title>
      <dc:creator>Mohamed Azmy</dc:creator>
      <pubDate>Mon, 05 Jan 2026 07:34:15 +0000</pubDate>
      <link>https://forem.com/azmy/understanding-coupling-afferent-vs-efferent-dependencies-in-system-design-5ha9</link>
      <guid>https://forem.com/azmy/understanding-coupling-afferent-vs-efferent-dependencies-in-system-design-5ha9</guid>
      <description>&lt;p&gt;
There are two important definitions when measuring &lt;strong&gt;coupling&lt;/strong&gt; between
parts of a codebase:
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;strong&gt;Afferent Coupling (Ca)&lt;/strong&gt;
    Measures how many other components depend on a given component.
  &lt;/li&gt;
  &lt;li&gt;
    &lt;strong&gt;Efferent Coupling (Ce)&lt;/strong&gt;
    Measures how many components a given component depends on.
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
Both metrics become &lt;strong&gt;critical&lt;/strong&gt; when you’re planning to change the
structure of a system.
&lt;/p&gt;

&lt;h2&gt;Why Coupling Matters During Refactoring&lt;/h2&gt;

&lt;p&gt;
Imagine you have a &lt;strong&gt;monolithic application&lt;/strong&gt; and you decide to migrate it
to &lt;strong&gt;microservices&lt;/strong&gt;.
&lt;/p&gt;

&lt;p&gt;
You’ll quickly notice shared classes such as
&lt;code&gt;Address&lt;/code&gt;, &lt;code&gt;Money&lt;/code&gt;, or &lt;code&gt;UserProfile&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;
In a monolith, reusing a class like &lt;code&gt;Address&lt;/code&gt; across multiple modules is
completely normal. But once you start decomposing the system, you must ask important
questions:
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;How many parts of the system depend on &lt;code&gt;Address&lt;/code&gt;?&lt;/li&gt;
  &lt;li&gt;If it changes or gets extracted, what will break?&lt;/li&gt;
  &lt;li&gt;Which modules will be affected directly or indirectly?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
This is exactly where &lt;strong&gt;coupling metrics&lt;/strong&gt; become valuable.
&lt;/p&gt;

&lt;h2&gt;Afferent Coupling (Ca)&lt;/h2&gt;

&lt;p&gt;
Afferent coupling tells you:
&lt;/p&gt;

&lt;p&gt;
&lt;strong&gt;“How many components rely on this one?”&lt;/strong&gt;
&lt;/p&gt;

&lt;p&gt;
High afferent coupling usually means:
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The component is widely used&lt;/li&gt;
  &lt;li&gt;Any change is risky&lt;/li&gt;
  &lt;li&gt;It must be stable and carefully designed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
Components with high Ca are often &lt;strong&gt;core domain concepts&lt;/strong&gt;.
&lt;/p&gt;

&lt;h2&gt;Efferent Coupling (Ce)&lt;/h2&gt;

&lt;p&gt;
Efferent coupling answers a different question:
&lt;/p&gt;

&lt;p&gt;
&lt;strong&gt;“How many components does this one depend on?”&lt;/strong&gt;
&lt;/p&gt;

&lt;p&gt;
High efferent coupling often indicates:
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Many external dependencies&lt;/li&gt;
  &lt;li&gt;Higher fragility&lt;/li&gt;
  &lt;li&gt;Poor separation of concerns&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Making Safer Architectural Decisions&lt;/h2&gt;

&lt;p&gt;
Measuring coupling helps you:
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Understand the impact of changes before making them&lt;/li&gt;
  &lt;li&gt;Reduce surprises during refactoring&lt;/li&gt;
  &lt;li&gt;Make architectural decisions based on data, not intuition&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Visualizing Dependencies&lt;/h2&gt;

&lt;p&gt;
Most modern platforms provide tools that analyze dependencies between code components.
&lt;/p&gt;

&lt;p&gt;
These tools usually visualize relationships between:
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Classes&lt;/li&gt;
  &lt;li&gt;Packages&lt;/li&gt;
  &lt;li&gt;Layers or modules&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
Often presented as a &lt;strong&gt;dependency matrix&lt;/strong&gt; that clearly shows who
depends on whom.
&lt;/p&gt;

&lt;h2&gt;Tooling Examples&lt;/h2&gt;

&lt;h3&gt;Java Ecosystem&lt;/h3&gt;

&lt;p&gt;
&lt;strong&gt;JDepend&lt;/strong&gt; is a popular Java tool that analyzes coupling at the package
level and provides clear metrics. This allows architectural decisions to be made
based on &lt;strong&gt;numbers&lt;/strong&gt;, not gut feelings.
&lt;/p&gt;

&lt;h3&gt;PHP Ecosystem&lt;/h3&gt;

&lt;p&gt;
In PHP, one of the most popular tools for dependency analysis is
&lt;strong&gt;Deptrac&lt;/strong&gt;.
&lt;/p&gt;

&lt;p&gt;
Deptrac is designed to:
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Analyze dependencies between layers or modules&lt;/li&gt;
  &lt;li&gt;Enforce architectural boundaries&lt;/li&gt;
  &lt;li&gt;Reveal hidden coupling in large PHP projects&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
It is especially useful for:
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Laravel applications&lt;/li&gt;
  &lt;li&gt;Modular monoliths&lt;/li&gt;
  &lt;li&gt;Microservice migration preparation&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;
Coupling analysis is not theoretical — it’s a &lt;strong&gt;practical tool&lt;/strong&gt;.
&lt;/p&gt;

&lt;p&gt;
If you work on large systems, maintain legacy code, plan to split a monolith, or want
to improve architecture incrementally, understanding
&lt;strong&gt;afferent and efferent coupling&lt;/strong&gt; will help you make safer decisions.
&lt;/p&gt;

&lt;p&gt;
Good architecture starts with &lt;strong&gt;visibility&lt;/strong&gt;, and coupling metrics give
you exactly that.
&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>backenddevelopment</category>
      <category>systemdesign</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Understanding Coupling: Afferent vs Efferent Dependencies in System Design</title>
      <dc:creator>Mohamed Azmy</dc:creator>
      <pubDate>Mon, 05 Jan 2026 07:34:15 +0000</pubDate>
      <link>https://forem.com/azmy/understanding-coupling-afferent-vs-efferent-dependencies-in-system-design-bfe</link>
      <guid>https://forem.com/azmy/understanding-coupling-afferent-vs-efferent-dependencies-in-system-design-bfe</guid>
      <description>&lt;p&gt;
There are two important definitions when measuring &lt;strong&gt;coupling&lt;/strong&gt; between
parts of a codebase:
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;strong&gt;Afferent Coupling (Ca)&lt;/strong&gt;
    Measures how many other components depend on a given component.
  &lt;/li&gt;
  &lt;li&gt;
    &lt;strong&gt;Efferent Coupling (Ce)&lt;/strong&gt;
    Measures how many components a given component depends on.
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
Both metrics become &lt;strong&gt;critical&lt;/strong&gt; when you’re planning to change the
structure of a system.
&lt;/p&gt;

&lt;h2&gt;Why Coupling Matters During Refactoring&lt;/h2&gt;

&lt;p&gt;
Imagine you have a &lt;strong&gt;monolithic application&lt;/strong&gt; and you decide to migrate it
to &lt;strong&gt;microservices&lt;/strong&gt;.
&lt;/p&gt;

&lt;p&gt;
You’ll quickly notice shared classes such as
&lt;code&gt;Address&lt;/code&gt;, &lt;code&gt;Money&lt;/code&gt;, or &lt;code&gt;UserProfile&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;
In a monolith, reusing a class like &lt;code&gt;Address&lt;/code&gt; across multiple modules is
completely normal. But once you start decomposing the system, you must ask important
questions:
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;How many parts of the system depend on &lt;code&gt;Address&lt;/code&gt;?&lt;/li&gt;
  &lt;li&gt;If it changes or gets extracted, what will break?&lt;/li&gt;
  &lt;li&gt;Which modules will be affected directly or indirectly?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
This is exactly where &lt;strong&gt;coupling metrics&lt;/strong&gt; become valuable.
&lt;/p&gt;

&lt;h2&gt;Afferent Coupling (Ca)&lt;/h2&gt;

&lt;p&gt;
Afferent coupling tells you:
&lt;/p&gt;

&lt;p&gt;
&lt;strong&gt;“How many components rely on this one?”&lt;/strong&gt;
&lt;/p&gt;

&lt;p&gt;
High afferent coupling usually means:
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The component is widely used&lt;/li&gt;
  &lt;li&gt;Any change is risky&lt;/li&gt;
  &lt;li&gt;It must be stable and carefully designed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
Components with high Ca are often &lt;strong&gt;core domain concepts&lt;/strong&gt;.
&lt;/p&gt;

&lt;h2&gt;Efferent Coupling (Ce)&lt;/h2&gt;

&lt;p&gt;
Efferent coupling answers a different question:
&lt;/p&gt;

&lt;p&gt;
&lt;strong&gt;“How many components does this one depend on?”&lt;/strong&gt;
&lt;/p&gt;

&lt;p&gt;
High efferent coupling often indicates:
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Many external dependencies&lt;/li&gt;
  &lt;li&gt;Higher fragility&lt;/li&gt;
  &lt;li&gt;Poor separation of concerns&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Making Safer Architectural Decisions&lt;/h2&gt;

&lt;p&gt;
Measuring coupling helps you:
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Understand the impact of changes before making them&lt;/li&gt;
  &lt;li&gt;Reduce surprises during refactoring&lt;/li&gt;
  &lt;li&gt;Make architectural decisions based on data, not intuition&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Visualizing Dependencies&lt;/h2&gt;

&lt;p&gt;
Most modern platforms provide tools that analyze dependencies between code components.
&lt;/p&gt;

&lt;p&gt;
These tools usually visualize relationships between:
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Classes&lt;/li&gt;
  &lt;li&gt;Packages&lt;/li&gt;
  &lt;li&gt;Layers or modules&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
Often presented as a &lt;strong&gt;dependency matrix&lt;/strong&gt; that clearly shows who
depends on whom.
&lt;/p&gt;

&lt;h2&gt;Tooling Examples&lt;/h2&gt;

&lt;h3&gt;Java Ecosystem&lt;/h3&gt;

&lt;p&gt;
&lt;strong&gt;JDepend&lt;/strong&gt; is a popular Java tool that analyzes coupling at the package
level and provides clear metrics. This allows architectural decisions to be made
based on &lt;strong&gt;numbers&lt;/strong&gt;, not gut feelings.
&lt;/p&gt;

&lt;h3&gt;PHP Ecosystem&lt;/h3&gt;

&lt;p&gt;
In PHP, one of the most popular tools for dependency analysis is
&lt;strong&gt;Deptrac&lt;/strong&gt;.
&lt;/p&gt;

&lt;p&gt;
Deptrac is designed to:
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Analyze dependencies between layers or modules&lt;/li&gt;
  &lt;li&gt;Enforce architectural boundaries&lt;/li&gt;
  &lt;li&gt;Reveal hidden coupling in large PHP projects&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
It is especially useful for:
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Laravel applications&lt;/li&gt;
  &lt;li&gt;Modular monoliths&lt;/li&gt;
  &lt;li&gt;Microservice migration preparation&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;
Coupling analysis is not theoretical — it’s a &lt;strong&gt;practical tool&lt;/strong&gt;.
&lt;/p&gt;

&lt;p&gt;
If you work on large systems, maintain legacy code, plan to split a monolith, or want
to improve architecture incrementally, understanding
&lt;strong&gt;afferent and efferent coupling&lt;/strong&gt; will help you make safer decisions.
&lt;/p&gt;

&lt;p&gt;
Good architecture starts with &lt;strong&gt;visibility&lt;/strong&gt;, and coupling metrics give
you exactly that.
&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>backenddevelopment</category>
      <category>systemdesign</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Shared Library vs Shared Service: A Better Alternative for Code Reuse</title>
      <dc:creator>Mohamed Azmy</dc:creator>
      <pubDate>Mon, 05 Jan 2026 07:26:39 +0000</pubDate>
      <link>https://forem.com/azmy/shared-library-vs-shared-service-a-better-alternative-for-code-reuse-1pmo</link>
      <guid>https://forem.com/azmy/shared-library-vs-shared-service-a-better-alternative-for-code-reuse-1pmo</guid>
      <description>&lt;p&gt;
The primary alternative to using a &lt;strong&gt;Shared Library&lt;/strong&gt; is using a
&lt;strong&gt;Shared Service&lt;/strong&gt;.
&lt;/p&gt;

&lt;p&gt;
Instead of reusing code through a shared library inside a Laravel project, you can
move shared logic into an &lt;strong&gt;independent service&lt;/strong&gt;, and let other services
or modules consume it via an &lt;strong&gt;API or client&lt;/strong&gt;.
&lt;/p&gt;

&lt;p&gt;
This approach shifts reuse from &lt;em&gt;code-level sharing&lt;/em&gt; to
&lt;em&gt;behavior-level sharing&lt;/em&gt;.
&lt;/p&gt;

&lt;h2&gt;A Practical Example&lt;/h2&gt;

&lt;p&gt;
Imagine you have multiple services that deal with customers, such as:
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Orders Service&lt;/li&gt;
  &lt;li&gt;Notifications Service&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
All of them need to &lt;strong&gt;check the customer’s balance&lt;/strong&gt; before performing
certain operations.
&lt;/p&gt;

&lt;h3&gt;The Shared Library Approach&lt;/h3&gt;

&lt;p&gt;
You could:
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Create a shared library&lt;/li&gt;
  &lt;li&gt;Import it into every service&lt;/li&gt;
  &lt;li&gt;Re-deploy all services whenever the logic changes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
This creates tight coupling and coordinated deployments.
&lt;/p&gt;

&lt;h3&gt;The Shared Service Approach&lt;/h3&gt;

&lt;p&gt;
Instead, you create a dedicated &lt;strong&gt;CustomerBalanceService&lt;/strong&gt;.
&lt;/p&gt;

&lt;p&gt;
Each service:
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Calls &lt;strong&gt;CustomerBalanceService&lt;/strong&gt; when it needs to validate customer balance&lt;/li&gt;
  &lt;li&gt;Does not own the balance calculation logic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
Now, if you:
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Change the calculation rules&lt;/li&gt;
  &lt;li&gt;Add new validation constraints&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
Only &lt;strong&gt;CustomerBalanceService&lt;/strong&gt; needs to be modified and deployed.
All consuming services automatically benefit from the change.
&lt;/p&gt;

&lt;h2&gt;Composition Over Inheritance&lt;/h2&gt;

&lt;p&gt;
The key idea here is that &lt;strong&gt;reuse happens through composition, not inheritance&lt;/strong&gt;.
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Services &lt;em&gt;use&lt;/em&gt; CustomerBalanceService&lt;/li&gt;
  &lt;li&gt;They do &lt;strong&gt;not&lt;/strong&gt; extend or inherit from its classes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
This provides:
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Greater flexibility&lt;/li&gt;
  &lt;li&gt;Better service autonomy&lt;/li&gt;
  &lt;li&gt;Looser coupling between components&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
Each service remains independent, with a clear contract between them.
&lt;/p&gt;

&lt;h2&gt;Architectural Trade-offs&lt;/h2&gt;

&lt;p&gt;
Like any architectural decision, shared services come with trade-offs.
&lt;/p&gt;

&lt;h3&gt;1. Change Risk&lt;/h3&gt;

&lt;p&gt;
Any change in the shared service can impact &lt;strong&gt;all dependent services&lt;/strong&gt;.
This requires:
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Strong versioning&lt;/li&gt;
  &lt;li&gt;Backward compatibility&lt;/li&gt;
  &lt;li&gt;Careful contract design&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;2. Performance&lt;/h3&gt;

&lt;p&gt;
Calling a shared service usually means:
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;A network call&lt;/li&gt;
  &lt;li&gt;Higher latency compared to a local library call&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
This must be evaluated carefully, especially in high-throughput paths.
&lt;/p&gt;

&lt;h3&gt;3. Fault Tolerance&lt;/h3&gt;

&lt;p&gt;
If the shared service goes down:
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;All dependent services may be affected&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
This makes the following essential parts of the design:
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Circuit breakers&lt;/li&gt;
  &lt;li&gt;Retries&lt;/li&gt;
  &lt;li&gt;Caching&lt;/li&gt;
  &lt;li&gt;Fallback strategies&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Final Thought&lt;/h2&gt;

&lt;p&gt;
Shared services promote:
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Better separation of concerns&lt;/li&gt;
  &lt;li&gt;Centralized business rules&lt;/li&gt;
  &lt;li&gt;Independent deployments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
But they also introduce:
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Runtime dependencies&lt;/li&gt;
  &lt;li&gt;Operational complexity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
Choose shared services when &lt;strong&gt;business logic truly belongs to a single authority&lt;/strong&gt;,
and be intentional about the trade-offs.
&lt;/p&gt;

&lt;p&gt;
Good architecture isn’t about eliminating problems —
it’s about choosing &lt;strong&gt;which problems you’re willing to manage&lt;/strong&gt;.
&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>backenddevelopment</category>
      <category>microservices</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Shared Library vs Shared Service: A Better Alternative for Code Reuse</title>
      <dc:creator>Mohamed Azmy</dc:creator>
      <pubDate>Mon, 05 Jan 2026 07:26:39 +0000</pubDate>
      <link>https://forem.com/azmy/shared-library-vs-shared-service-a-better-alternative-for-code-reuse-1j2n</link>
      <guid>https://forem.com/azmy/shared-library-vs-shared-service-a-better-alternative-for-code-reuse-1j2n</guid>
      <description>&lt;p&gt;
The primary alternative to using a &lt;strong&gt;Shared Library&lt;/strong&gt; is using a
&lt;strong&gt;Shared Service&lt;/strong&gt;.
&lt;/p&gt;

&lt;p&gt;
Instead of reusing code through a shared library inside a Laravel project, you can
move shared logic into an &lt;strong&gt;independent service&lt;/strong&gt;, and let other services
or modules consume it via an &lt;strong&gt;API or client&lt;/strong&gt;.
&lt;/p&gt;

&lt;p&gt;
This approach shifts reuse from &lt;em&gt;code-level sharing&lt;/em&gt; to
&lt;em&gt;behavior-level sharing&lt;/em&gt;.
&lt;/p&gt;

&lt;h2&gt;A Practical Example&lt;/h2&gt;

&lt;p&gt;
Imagine you have multiple services that deal with customers, such as:
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Orders Service&lt;/li&gt;
  &lt;li&gt;Notifications Service&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
All of them need to &lt;strong&gt;check the customer’s balance&lt;/strong&gt; before performing
certain operations.
&lt;/p&gt;

&lt;h3&gt;The Shared Library Approach&lt;/h3&gt;

&lt;p&gt;
You could:
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Create a shared library&lt;/li&gt;
  &lt;li&gt;Import it into every service&lt;/li&gt;
  &lt;li&gt;Re-deploy all services whenever the logic changes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
This creates tight coupling and coordinated deployments.
&lt;/p&gt;

&lt;h3&gt;The Shared Service Approach&lt;/h3&gt;

&lt;p&gt;
Instead, you create a dedicated &lt;strong&gt;CustomerBalanceService&lt;/strong&gt;.
&lt;/p&gt;

&lt;p&gt;
Each service:
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Calls &lt;strong&gt;CustomerBalanceService&lt;/strong&gt; when it needs to validate customer balance&lt;/li&gt;
  &lt;li&gt;Does not own the balance calculation logic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
Now, if you:
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Change the calculation rules&lt;/li&gt;
  &lt;li&gt;Add new validation constraints&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
Only &lt;strong&gt;CustomerBalanceService&lt;/strong&gt; needs to be modified and deployed.
All consuming services automatically benefit from the change.
&lt;/p&gt;

&lt;h2&gt;Composition Over Inheritance&lt;/h2&gt;

&lt;p&gt;
The key idea here is that &lt;strong&gt;reuse happens through composition, not inheritance&lt;/strong&gt;.
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Services &lt;em&gt;use&lt;/em&gt; CustomerBalanceService&lt;/li&gt;
  &lt;li&gt;They do &lt;strong&gt;not&lt;/strong&gt; extend or inherit from its classes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
This provides:
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Greater flexibility&lt;/li&gt;
  &lt;li&gt;Better service autonomy&lt;/li&gt;
  &lt;li&gt;Looser coupling between components&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
Each service remains independent, with a clear contract between them.
&lt;/p&gt;

&lt;h2&gt;Architectural Trade-offs&lt;/h2&gt;

&lt;p&gt;
Like any architectural decision, shared services come with trade-offs.
&lt;/p&gt;

&lt;h3&gt;1. Change Risk&lt;/h3&gt;

&lt;p&gt;
Any change in the shared service can impact &lt;strong&gt;all dependent services&lt;/strong&gt;.
This requires:
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Strong versioning&lt;/li&gt;
  &lt;li&gt;Backward compatibility&lt;/li&gt;
  &lt;li&gt;Careful contract design&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;2. Performance&lt;/h3&gt;

&lt;p&gt;
Calling a shared service usually means:
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;A network call&lt;/li&gt;
  &lt;li&gt;Higher latency compared to a local library call&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
This must be evaluated carefully, especially in high-throughput paths.
&lt;/p&gt;

&lt;h3&gt;3. Fault Tolerance&lt;/h3&gt;

&lt;p&gt;
If the shared service goes down:
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;All dependent services may be affected&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
This makes the following essential parts of the design:
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Circuit breakers&lt;/li&gt;
  &lt;li&gt;Retries&lt;/li&gt;
  &lt;li&gt;Caching&lt;/li&gt;
  &lt;li&gt;Fallback strategies&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Final Thought&lt;/h2&gt;

&lt;p&gt;
Shared services promote:
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Better separation of concerns&lt;/li&gt;
  &lt;li&gt;Centralized business rules&lt;/li&gt;
  &lt;li&gt;Independent deployments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
But they also introduce:
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Runtime dependencies&lt;/li&gt;
  &lt;li&gt;Operational complexity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
Choose shared services when &lt;strong&gt;business logic truly belongs to a single authority&lt;/strong&gt;,
and be intentional about the trade-offs.
&lt;/p&gt;

&lt;p&gt;
Good architecture isn’t about eliminating problems —
it’s about choosing &lt;strong&gt;which problems you’re willing to manage&lt;/strong&gt;.
&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>backenddevelopment</category>
      <category>microservices</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Microservices Are Not Always the Right Answer</title>
      <dc:creator>Mohamed Azmy</dc:creator>
      <pubDate>Tue, 30 Dec 2025 12:59:41 +0000</pubDate>
      <link>https://forem.com/azmy/microservices-are-not-always-the-right-answer-4gji</link>
      <guid>https://forem.com/azmy/microservices-are-not-always-the-right-answer-4gji</guid>
      <description>&lt;p&gt;It’s not always correct to split a system into microservices.&lt;br&gt;
Just like there are valid reasons to &lt;strong&gt;break a service apart&lt;/strong&gt;, there are also strong reasons to &lt;strong&gt;keep services together&lt;/strong&gt; — or not split them at all in the first place.&lt;/p&gt;

&lt;p&gt;These reasons are known as &lt;strong&gt;Granularity Integrators&lt;/strong&gt;.&lt;br&gt;
They are the factors that make you pause before decomposing a service, or justify keeping it large.&lt;/p&gt;

&lt;p&gt;The real skill in choosing the right service size is &lt;strong&gt;balancing decomposition drivers with integration drivers, not blindly following one direction&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Below are the &lt;strong&gt;four most important reasons&lt;/strong&gt; to integrate services or avoid splitting them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Database Transactions (ACID)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If an operation requires a strong ACID transaction across multiple parts of the system, those parts usually should not be separate services.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example (Laravel)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Creating an &lt;strong&gt;Order&lt;/strong&gt; and updating &lt;strong&gt;Stock&lt;/strong&gt; must happen together.&lt;br&gt;
If one fails, both must roll back.&lt;/p&gt;

&lt;p&gt;If these operations live in separate services, you’ll need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Distributed transactions&lt;/li&gt;
&lt;li&gt;Complex compensation logic&lt;/li&gt;
&lt;li&gt;Higher failure scenarios&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this case, &lt;strong&gt;integration or a monolith is a logical and simpler choice&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Workflow &amp;amp; Choreography Complexity&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ask yourself:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do services need to communicate heavily to complete a single business operation?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:-&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Order Service&lt;/li&gt;
&lt;li&gt;Payment Service&lt;/li&gt;
&lt;li&gt;Shipping Service&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If every order requires constant back-and-forth communication between these services, splitting them may:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Increase latency&lt;/li&gt;
&lt;li&gt;Increase operational complexity&lt;/li&gt;
&lt;li&gt;Make debugging much harder&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;High communication overhead is often a sign that &lt;strong&gt;separation may hurt more than help&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Shared Code&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Do multiple services depend on the &lt;strong&gt;same complex logic&lt;/strong&gt;?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example (Laravel)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Imagine having complex &lt;strong&gt;validation logic&lt;/strong&gt; reused across several services.&lt;/p&gt;

&lt;p&gt;If you end up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Copying the same code everywhere&lt;/li&gt;
&lt;li&gt;Or creating shared services with frequent calls&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then service separation becomes noisy and fragile.&lt;br&gt;
In such cases, &lt;strong&gt;keeping the logic together can be cleaner and more maintainable&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Database Relationships&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Even if you can split the code — can you split the data?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Entities like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Users&lt;/li&gt;
&lt;li&gt;Orders&lt;/li&gt;
&lt;li&gt;Payments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Often have &lt;strong&gt;strong relational dependencies&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If services require:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Frequent joins&lt;/li&gt;
&lt;li&gt;Strong consistency guarantees&lt;/li&gt;
&lt;li&gt;Tight coupling at the data level&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then splitting them introduces:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Complex synchronization&lt;/li&gt;
&lt;li&gt;Consistency issues&lt;/li&gt;
&lt;li&gt;Endless edge cases&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sometimes, &lt;strong&gt;the database model itself argues against microservices&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Final Thoughts&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Microservices are &lt;strong&gt;not a goal&lt;/strong&gt; — they are an architectural choice.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Over-splitting increases complexity&lt;/li&gt;
&lt;li&gt;Over-integrating reduces flexibility&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Good architecture is about &lt;strong&gt;balance&lt;/strong&gt;.&lt;br&gt;
You split or integrate based on &lt;strong&gt;real constraints and domain needs&lt;/strong&gt;, not trends or hype.&lt;/p&gt;

&lt;p&gt;Design for reality — not fashion.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>backend</category>
      <category>laravel</category>
      <category>microservices</category>
    </item>
    <item>
      <title>Extensibility: A Strong Reason to Split a Large Service</title>
      <dc:creator>Mohamed Azmy</dc:creator>
      <pubDate>Tue, 30 Dec 2025 07:34:00 +0000</pubDate>
      <link>https://forem.com/azmy/extensibility-a-strong-reason-to-split-a-large-service-4i9o</link>
      <guid>https://forem.com/azmy/extensibility-a-strong-reason-to-split-a-large-service-4i9o</guid>
      <description>&lt;p&gt;One of the most important reasons to break down a large service into smaller ones is extensibility — the ability to add new functionality easily as the service context grows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A Practical Example: Payment Service&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Imagine you have a Payment Service responsible for handling payments and refunds using multiple payment methods, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Credit Cards.&lt;/li&gt;
&lt;li&gt;Gift Cards.&lt;/li&gt;
&lt;li&gt;PayPal.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now the business decides to support additional payment methods:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Store Credit from returns.&lt;/li&gt;
&lt;li&gt;Reward Points.&lt;/li&gt;
&lt;li&gt;Apple Pay or Samsung Pay.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The Problem with One Large Service&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If all of this logic lives inside one large service, every time you add a new payment method, you are forced to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Re-test all existing payment methods, not just the new one.&lt;/li&gt;
&lt;li&gt;Re-deploy the entire service, including unchanged functionality.&lt;/li&gt;
&lt;li&gt;Deal with larger test suites and higher risk of regression.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This increases development time, raises risk, and makes it harder to introduce new payment methods quickly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Splitting by Responsibility&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now imagine splitting that large service into smaller, focused services:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Credit Card Processing Service.&lt;/li&gt;
&lt;li&gt;Gift Card Processing Service.&lt;/li&gt;
&lt;li&gt;PayPal Processing Service.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With this approach, adding a new payment method like Reward Points means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Developing only one new service.&lt;/li&gt;
&lt;li&gt;Testing only that service.&lt;/li&gt;
&lt;li&gt;Deploying it independently.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Faster development.&lt;/li&gt;
&lt;li&gt;Smaller and more focused test scopes.&lt;/li&gt;
&lt;li&gt;Lower risk during deployment.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;When Extensibility Is a Valid Reason&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use extensibility as a reason to split services only if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You are confident that new functionality will be added frequently in the future.&lt;/li&gt;
&lt;li&gt;Or the domain naturally evolves over time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Examples&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Notification Service:&lt;br&gt;
It’s relatively rare to add new notification channels (SMS, Email, Letters), so keeping it as a single service often makes sense.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Payment Processing:&lt;br&gt;
New payment methods are very likely to be introduced, so splitting services by payment type is a practical and scalable design choice.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Final Thought&lt;/strong&gt;&lt;br&gt;
Extensibility is not about splitting services prematurely — it’s about &lt;strong&gt;anticipating growth where growth is expected&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Design your services based on how the domain evolves, not just on how it looks today.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>microservices</category>
      <category>backend</category>
      <category>laravel</category>
    </item>
    <item>
      <title>Auditing Sensitive Data Changes in Laravel: Securing High-Risk Operations</title>
      <dc:creator>Mohamed Azmy</dc:creator>
      <pubDate>Sun, 31 Aug 2025 06:53:37 +0000</pubDate>
      <link>https://forem.com/azmy/auditing-sensitive-data-changes-in-laravel-securing-high-risk-operations-9n3</link>
      <guid>https://forem.com/azmy/auditing-sensitive-data-changes-in-laravel-securing-high-risk-operations-9n3</guid>
      <description>&lt;p&gt;When working with sensitive data—such as &lt;strong&gt;financial records&lt;/strong&gt;, &lt;strong&gt;user roles&lt;/strong&gt;, or &lt;strong&gt;confidential information—tracking&lt;/strong&gt; changes is &lt;strong&gt;not optional&lt;/strong&gt;, it’s &lt;strong&gt;mandatory&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Unlike general model updates, sensitive data changes must be audited separately to ensure that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You know exactly who changed the data.&lt;/li&gt;
&lt;li&gt;You can see what the data was before and after.&lt;/li&gt;
&lt;li&gt;You maintain compliance with regulations (GDPR, HIPAA, PCI DSS, etc.).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In Laravel, this can be achieved by combining &lt;strong&gt;Events&lt;/strong&gt;, &lt;strong&gt;Middleware&lt;/strong&gt;, and &lt;strong&gt;Custom Audit Logs&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Sensitive Data Auditing is Different&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Not all model changes are equal. Updating a blog title is harmless, but changing a user’s balance, password, or permissions is critical.&lt;/li&gt;
&lt;li&gt;Sensitive changes need extra auditing logic: e.g., store the user’s IP, device, or even require double approval.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;: Auditing Balance Changes in Laravel&lt;/p&gt;

&lt;p&gt;01) Install the Package&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;composer require owen-it/laravel-auditing
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;02) Publish Config File&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php artisan vendor:publish --provider "OwenIt\Auditing\AuditingServiceProvider"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create a configuration file at &lt;code&gt;config/audit.php&lt;/code&gt;.&lt;br&gt;
03) Run Migration&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php artisan migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;04) Enable Auditing on a Model&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;use OwenIt\Auditing\Contracts\Auditable;

class Post extends Model implements Auditable
{
    use \OwenIt\Auditing\Auditable;

    protected $fillable = ['title', 'content'];
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By adding the &lt;code&gt;Auditable&lt;/code&gt; trait, Laravel will now automatically log every change to this model.&lt;/p&gt;

&lt;p&gt;05) Test It Out&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$post = Post::find(1);
$post-&amp;gt;update(['title' =&amp;gt; 'New Title']);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;06) Check the Audit Table&lt;br&gt;
A new record will be created in the &lt;code&gt;audits&lt;/code&gt; table:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "user_id": 2,
  "event": "updated",
  "auditable_type": "App\\Models\\Post",
  "auditable_id": 1,
  "old_values": { "title": "Old Title" },
  "new_values": { "title": "New Title" },
  "created_at": "2025-08-31 10:15:00"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here you can clearly see:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which user made the change (&lt;code&gt;user_id&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;What was changed (&lt;code&gt;old_values&lt;/code&gt; → &lt;code&gt;new_values&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;When the change happened (&lt;code&gt;created_at&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Benefits of Auditing&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;✔ Automatic tracking of changes.&lt;br&gt;
✔ Provides accountability and transparency.&lt;br&gt;
✔ Useful for compliance and regulatory requirements.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best Practices for Sensitive Data Auditing&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;✔ Audit only sensitive operations (balances, roles, passwords, permissions).&lt;br&gt;
✔ Store who, what, when, where (IP/device).&lt;br&gt;
✔ Don’t store raw sensitive data (e.g., passwords) → use masked/encrypted logs.&lt;br&gt;
✔ Regularly review audit logs and set up alerts for suspicious activity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Auditing sensitive data changes in Laravel gives you a second layer of defense beyond normal logging. By designing a custom auditing system, you can selectively monitor critical operations and ensure that your application is both secure and compliant.&lt;/p&gt;

&lt;p&gt;Instead of tracking every model update, focus on what really matters—high-risk data changes that could affect users, finances, or security.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>security</category>
      <category>backend</category>
      <category>laravel</category>
    </item>
    <item>
      <title>Fixing CORS Not Working in Laravel 12 (Custom Middleware Solution)</title>
      <dc:creator>Mohamed Azmy</dc:creator>
      <pubDate>Tue, 05 Aug 2025 10:01:55 +0000</pubDate>
      <link>https://forem.com/azmy/fixing-cors-not-working-in-laravel-12-custom-middleware-solution-1p0</link>
      <guid>https://forem.com/azmy/fixing-cors-not-working-in-laravel-12-custom-middleware-solution-1p0</guid>
      <description>&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%2Fogyfs7dhs8zhs247f5zm.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%2Fogyfs7dhs8zhs247f5zm.png" alt=" " width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
When working with Laravel 12 and building APIs consumed by frontend apps (like React, Vue, etc.), you might run into the dreaded CORS error — even when you think you’ve configured it correctly.&lt;/p&gt;

&lt;p&gt;I did everything Laravel told me to do, but CORS was still broken. Eventually, I found a fix using custom middleware, and I’m sharing it here so you don’t waste hours like I did.&lt;/p&gt;

&lt;p&gt;The Problem&lt;/p&gt;

&lt;p&gt;I kept seeing this CORS error in the browser:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Access to fetch at 'http://example.com/api/...'
from origin 'http://localhost:3000'
has been blocked by CORS policy:
No 'Access-Control-Allow-Origin' header is present on the requested resource.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even though I had this set in config/cors.php:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;'paths' =&amp;gt; ['api/*'],
'allowed_origins' =&amp;gt; ['*'],
'supports_credentials' =&amp;gt; true,
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nothing worked. Laravel’s built-in HandleCors middleware wasn’t doing its job.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Solution (Custom Middleware)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Instead of relying on Laravel’s built-in CORS system, I created my own middleware and manually registered it.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Step 1: Create Middleware&lt;/strong&gt;&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php artisan make:middleware Cors
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then open the file at &lt;code&gt;app/Http/Middleware/Cors.php&lt;/code&gt; and paste this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
&amp;lt;?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

class Cors
{
    public function handle(Request $request, Closure $next): Response
    {
        $response = $next($request);

        $response-&amp;gt;header('Access-Control-Allow-Origin', '*');
        $response-&amp;gt;header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
        $response-&amp;gt;header('Access-Control-Allow-Headers', 'Origin, Content-Type, Accept, Authorization');

        return $response;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;em&gt;Step 2: Register Middleware in Laravel 12&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In Laravel 12,&lt;code&gt;Http\Kernel.php&lt;/code&gt; is gone — so you register middleware in &lt;code&gt;bootstrap/app.php&lt;/code&gt; instead.&lt;/p&gt;

&lt;p&gt;If you want it applied globally to all requests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$app-&amp;gt;middleware([
    \App\Http\Middleware\Cors::class,
]);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want to apply it only to certain routes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$app-&amp;gt;routeMiddleware([
    'cors.custom' =&amp;gt; \App\Http\Middleware\Cors::class,
]);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;em&gt;Step 3: Apply It to Routes (if route-based)&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In your &lt;code&gt;routes/api.php&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Route::middleware(['cors.custom'])-&amp;gt;group(function () {
    Route::get('/example', [ExampleController::class, 'index']);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why This Works&lt;/p&gt;

&lt;p&gt;Laravel’s default CORS middleware can sometimes silently fail due to misconfiguration or changes in the request flow. By taking full control with a custom middleware, you ensure the correct headers are returned with every response.&lt;/p&gt;

&lt;p&gt;This is especially useful when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;    You’re using Laravel 12’s minimal setup&lt;/li&gt;
&lt;li&gt;    You’re building SPAs or frontends on a different domain&lt;/li&gt;
&lt;li&gt;    The default config doesn’t work even after clearing caches&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Final Thoughts&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;CORS issues are frustrating, and Laravel’s magic sometimes gets in the way. This manual solution worked for me and might help you too.&lt;/p&gt;

&lt;p&gt;Let me know if this helped — or if you have a cleaner workaround!&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>php</category>
      <category>api</category>
      <category>middleware</category>
    </item>
  </channel>
</rss>
