<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ architecture - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ architecture - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Wed, 27 May 2026 16:21:16 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/architecture/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Navigate Microservices as a Frontend Engineer ]]>
                </title>
                <description>
                    <![CDATA[ Most frontend engineers don't choose microservices. They inherit them. One day you're fetching data from a single API, and the next you're stitching together responses from five services, each with it ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-navigate-microservices-as-a-frontend-engineer/</link>
                <guid isPermaLink="false">69f8de9b46610fd6060f5251</guid>
                
                    <category>
                        <![CDATA[ Microservices ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Frontend Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ architecture ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Abisoye Alli-Balogun ]]>
                </dc:creator>
                <pubDate>Mon, 04 May 2026 17:59:55 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/uploads/covers/5e1e335a7a1d3fcc59028c64/6a10811b-1150-490a-8f29-28797fd39861.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Most frontend engineers don't choose microservices. They inherit them. One day you're fetching data from a single API, and the next you're stitching together responses from five services, each with its own contract, its own failure modes, and its own idea of what a "user" looks like.</p>
<p>The backend team talks about bounded contexts, eventual consistency, and service meshes. You're thinking about loading states, stale data, and why the checkout page breaks when the inventory service is slow.</p>
<p>This article is for frontend engineers working in microservice environments. You'll learn how to consume multiple service APIs without creating a tangled mess, how to handle partial failures gracefully in the UI, how to manage distributed state across services, and how to work effectively with backend teams on API contracts <strong>because half the battle is communication, not code</strong>.</p>
<p>The goal is not to turn you into a backend engineer, it's to give you the mental models and patterns that make frontend development in a microservice world less painful.</p>
<h3 id="heading-prerequisites">Prerequisites</h3>
<p>To get the most out of this article, you should be familiar with:</p>
<ul>
<li><p>React or a similar component framework (the examples use React and TypeScript)</p>
</li>
<li><p>Basic understanding of REST APIs and HTTP</p>
</li>
<li><p>Experience fetching data in frontend applications (fetch, Axios, or React Query)</p>
</li>
<li><p>General awareness of what microservices are (you don't need to have built one)</p>
</li>
</ul>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a href="#heading-the-frontends-microservice-problem">The Frontend's Microservice Problem</a></p>
</li>
<li><p><a href="#heading-pattern-1-the-backend-for-frontend-bff">Pattern 1: The Backend-for-Frontend (BFF)</a></p>
</li>
<li><p><a href="#heading-pattern-2-handling-partial-failures-in-the-ui">Pattern 2: Handling Partial Failures in the UI</a></p>
</li>
<li><p><a href="#heading-pattern-3-managing-distributed-state">Pattern 3: Managing Distributed State</a></p>
</li>
<li><p><a href="#heading-pattern-4-taming-multiple-api-contracts">Pattern 4: Taming Multiple API Contracts</a></p>
</li>
<li><p><a href="#heading-pattern-5-timeout-budgets-for-page-assembly">Pattern 5: Timeout Budgets for Page Assembly</a></p>
</li>
<li><p><a href="#heading-pattern-6-error-boundaries-per-service">Pattern 6: Error Boundaries Per Service</a></p>
</li>
<li><p><a href="#heading-working-with-backend-teams-on-contracts">Working With Backend Teams on Contracts</a></p>
</li>
<li><p><a href="#heading-when-to-push-back">When to Push Back</a></p>
</li>
<li><p><a href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-the-frontends-microservice-problem">The Frontend's Microservice Problem</h2>
<p>In a monolithic architecture, the frontend talks to one API. That API owns the database, handles the business logic, and returns exactly the shape of data the UI needs. Life is simple.</p>
<p>In a microservice architecture, that single API fractures into many:</p>
<pre><code class="language-text">Monolith:
  Browser → API → Database

Microservices:
  Browser → API Gateway → User Service
                        → Order Service
                        → Inventory Service
                        → Payment Service
                        → Notification Service
</code></pre>
<p>Each of those services is owned by a different team, deployed independently, and may use different data formats or conventions. As a frontend engineer, you now have several new problems:</p>
<ol>
<li><p><strong>Multiple contracts:</strong> Each service has its own API shape. A "product" in the inventory service has different fields than a "product" in the catalog service.</p>
</li>
<li><p><strong>Partial failures:</strong> The order service might respond in 50 ms while the recommendation service times out. Your UI needs to handle both.</p>
</li>
<li><p><strong>Data consistency:</strong> A user updates their address, but the order service still shows the old one because it hasn't synced yet.</p>
</li>
<li><p><strong>Increased latency:</strong> Assembling a single page might require three or four API calls instead of one.</p>
</li>
</ol>
<p>These aren't backend problems that happen to affect the frontend. They're fundamentally frontend problems that require frontend solutions.</p>
<h2 id="heading-pattern-1-the-backend-for-frontend-bff">Pattern 1: The Backend-for-Frontend (BFF)</h2>
<p>The most impactful pattern for frontend teams in a microservice world is the Backend-for-Frontend. A BFF is a thin API layer that sits between the browser and the microservices. It's owned by the frontend team and exists to serve the frontend's specific needs.</p>
<pre><code class="language-text">Without BFF:
  Browser → User Service    (call 1)
  Browser → Order Service   (call 2)
  Browser → Inventory Service (call 3)
  3 round trips, 3 contracts to manage

With BFF:
  Browser → BFF → User Service
                → Order Service
                → Inventory Service
  1 round trip, 1 contract to manage
</code></pre>
<p>The BFF aggregates calls, transforms responses into the shapes your components need, and handles cross-service concerns like authentication token forwarding.</p>
<pre><code class="language-typescript">// BFF endpoint: GET /api/order-summary/:orderId
// Aggregates data from three services into one frontend-friendly response
import express from "express";

const router = express.Router();

router.get("/api/order-summary/:orderId", async (req, res) =&gt; {
  const { orderId } = req.params;
  const token = req.headers.authorization;

  try {
    const [order, customer, shipment] = await Promise.allSettled([
      fetch(`\({ORDER_SERVICE}/orders/\){orderId}`, {
        headers: { Authorization: token },
      }).then((r) =&gt; r.json()),
      fetch(`\({USER_SERVICE}/users/\){req.userId}`, { // userId set by auth middleware
        headers: { Authorization: token },
      }).then((r) =&gt; r.json()),
      fetch(`\({SHIPPING_SERVICE}/shipments?orderId=\){orderId}`, {
        headers: { Authorization: token },
      }).then((r) =&gt; r.json()),
    ]);

    res.json({
      order: order.status === "fulfilled" ? order.value : null,
      customer: customer.status === "fulfilled" ? customer.value : null,
      shipment: shipment.status === "fulfilled" ? shipment.value : null,
      errors: [order, customer, shipment]
        .filter((r) =&gt; r.status === "rejected")
        .map((r) =&gt; r.reason.message),
    });
  } catch (error) {
    res.status(500).json({ error: "Failed to assemble order summary" });
  }
});
</code></pre>
<p>Notice the use of <code>Promise.allSettled</code> instead of <code>Promise.all</code>. This is critical in a microservice environment. <code>Promise.all</code> fails fast: if any one service is down, the entire request fails. <code>Promise.allSettled</code> lets you return partial data, which leads directly to the next pattern.</p>
<h3 id="heading-when-to-use-a-bff">When to Use a BFF</h3>
<p>A BFF is worth the investment when:</p>
<ul>
<li><p>Your frontend aggregates data from three or more services per page</p>
</li>
<li><p>Different clients (web, mobile, admin) need different data shapes from the same services</p>
</li>
<li><p>You want the frontend team to control response shapes without waiting on backend teams</p>
</li>
</ul>
<p>A BFF isn't necessary when:</p>
<ul>
<li><p>You have an API gateway that already handles aggregation (for example, Apollo Federation for GraphQL)</p>
</li>
<li><p>You only consume one or two services</p>
</li>
<li><p>Your backend teams already provide frontend-optimized endpoints</p>
</li>
</ul>
<h2 id="heading-pattern-2-handling-partial-failures-in-the-ui">Pattern 2: Handling Partial Failures in the UI</h2>
<p>In a monolith, a request either succeeds or fails. In a microservice world, it can partially succeed. The order data loads fine, but the recommendation service is down. The product details are available, but the review service is slow.</p>
<p>Your UI needs to handle this gracefully. The key principle: <strong>never let a non-critical service failure break a critical user flow.</strong></p>
<pre><code class="language-typescript">// Types for partial data loading
interface ServiceResult&lt;T&gt; {
  data: T | null;
  status: "loaded" | "error" | "loading";
  error?: string;
}

interface OrderPageData {
  order: ServiceResult&lt;Order&gt;;
  recommendations: ServiceResult&lt;Product[]&gt;;
  reviews: ServiceResult&lt;Review[]&gt;;
}
</code></pre>
<p>Build your components to render independently based on what data is available:</p>
<pre><code class="language-typescript">function OrderPage({ orderId }: { orderId: string }) {
  const { order, recommendations, reviews } = useOrderPageData(orderId);

  // Critical: order must load or the page makes no sense
  if (order.status === "loading") return &lt;OrderSkeleton /&gt;;
  if (order.status === "error") return &lt;ErrorPage message={order.error} /&gt;;

  return (
    &lt;div&gt;
      {/* Critical section: always rendered */}
      &lt;OrderDetails order={order.data} /&gt;

      {/* Non-critical: degrades gracefully */}
      &lt;section aria-label="Recommendations"&gt;
        {recommendations.status === "loaded" ? (
          &lt;RecommendationCarousel products={recommendations.data} /&gt;
        ) : recommendations.status === "error" ? (
          &lt;EmptyState message="Recommendations Unavailable" /&gt;
        ) : (
          &lt;CarouselSkeleton /&gt;
        )}
      &lt;/section&gt;

      {/* Non-critical: degrades gracefully */}
      &lt;section aria-label="Customer reviews"&gt;
        {reviews.status === "loaded" ? (
          &lt;ReviewList reviews={reviews.data} /&gt;
        ) : reviews.status === "error" ? (
          &lt;EmptyState message="Reviews unavailable right now" /&gt;
        ) : (
          &lt;ReviewSkeleton /&gt;
        )}
      &lt;/section&gt;
    &lt;/div&gt;
  );
}
</code></pre>
<h3 id="heading-classifying-critical-vs-non-critical-data">Classifying Critical vs. Non-Critical Data</h3>
<p>Not all data on a page is equally important. Before building any page that pulls from multiple services, classify each data source:</p>
<table>
<thead>
<tr>
<th>Data Source</th>
<th>Critical?</th>
<th>Failure Strategy</th>
</tr>
</thead>
<tbody><tr>
<td>Order details</td>
<td>Yes</td>
<td>Show error page, block the entire view</td>
</tr>
<tr>
<td>Customer info</td>
<td>Yes</td>
<td>Show error page</td>
</tr>
<tr>
<td>Recommendations</td>
<td>No</td>
<td>Hide the section, show empty state</td>
</tr>
<tr>
<td>Reviews</td>
<td>No</td>
<td>Show "reviews unavailable" message</td>
</tr>
<tr>
<td>Recently viewed</td>
<td>No</td>
<td>Hide silently</td>
</tr>
</tbody></table>
<p>This classification should be a conscious decision made with your product team, not something you discover when a service goes down in production.</p>
<h2 id="heading-pattern-3-managing-distributed-state">Pattern 3: Managing Distributed State</h2>
<p>In a monolithic world, the server is the single source of truth. In a microservice world, truth is distributed. The user service knows the user's current address. The order service has a snapshot of the address at the time of the order. These might not match.</p>
<h3 id="heading-stale-data-and-cache-boundaries">Stale Data and Cache Boundaries</h3>
<p>When your frontend caches data from multiple services, you need to think about cache boundaries. Data from different services goes stale at different rates.</p>
<pre><code class="language-typescript">// Configure cache times based on how frequently the underlying data changes
const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      staleTime: 30_000, // Default: 30 seconds
    },
  },
});

// Product catalog: changes infrequently
function useProduct(productId: string) {
  return useQuery({
    queryKey: ["product", productId],
    queryFn: () =&gt; fetchProduct(productId),
    staleTime: 5 * 60_000, // 5 minutes: catalog updates are rare
  });
}

// Inventory levels: changes constantly
function useStockLevel(productId: string) {
  return useQuery({
    queryKey: ["stock", productId],
    queryFn: () =&gt; fetchStockLevel(productId),
    staleTime: 10_000, // 10 seconds: stock changes with every purchase
    refetchInterval: 30_000, // Poll every 30 seconds on active pages
  });
}

// User's own order: should reflect latest state
function useOrder(orderId: string) {
  return useQuery({
    queryKey: ["order", orderId],
    queryFn: () =&gt; fetchOrder(orderId),
    staleTime: 0, // Always refetch: user expects to see their latest action
  });
}
</code></pre>
<p>The mistake is treating all cached data the same. Product information from the catalog service can be cached for minutes. Stock levels from the inventory service need to be refreshed much more frequently. A user's own order data should always be fresh because they just performed an action and expect to see the result.</p>
<h3 id="heading-cross-service-invalidation">Cross-Service Invalidation</h3>
<p>The trickiest part of distributed state is knowing when to invalidate. When a user places an order, you need to:</p>
<ol>
<li><p>Invalidate the order list (order service)</p>
</li>
<li><p>Invalidate the stock level (inventory service)</p>
</li>
<li><p>Invalidate the user's loyalty points (user service)</p>
</li>
</ol>
<pre><code class="language-typescript">// After a successful order placement, invalidate across service boundaries
async function placeOrder(cart: Cart): Promise&lt;Order&gt; {
  const order = await api.post("/api/orders", { items: cart.items });

  // Invalidate data from multiple services that this action affected
  queryClient.invalidateQueries({ queryKey: ["orders"] });
  queryClient.invalidateQueries({ queryKey: ["stock"] });
  queryClient.invalidateQueries({ queryKey: ["loyalty-points"] });

  // Optimistically update the cart (owned by the frontend)
  queryClient.setQueryData(["cart"], { items: [] });

  return order;
}
</code></pre>
<p>This is manual and error-prone. Every time a new service cares about order events, you need to remember to add an invalidation here.</p>
<p>For more robust alternatives, you can use server-sent events or WebSocket connections to let the backend push invalidation signals to the frontend, or adopt a pub/sub pattern within your client-side state layer where cache keys subscribe to domain events.</p>
<p>These approaches are beyond this article's scope, but worth exploring once your invalidation table grows past a dozen entries.</p>
<p>In the meantime, documenting these cross-service dependencies in a table helps:</p>
<table>
<thead>
<tr>
<th>User Action</th>
<th>Services Affected</th>
<th>Cache Keys to Invalidate</th>
</tr>
</thead>
<tbody><tr>
<td>Place order</td>
<td>Order, Inventory, User</td>
<td><code>orders</code>, <code>stock</code>, <code>loyalty-points</code>, <code>cart</code></td>
</tr>
<tr>
<td>Update address</td>
<td>User, Shipping</td>
<td><code>user-profile</code>, <code>shipping-estimates</code></td>
</tr>
<tr>
<td>Write review</td>
<td>Reviews, Product</td>
<td><code>reviews</code>, <code>product</code> (rating changes)</td>
</tr>
</tbody></table>
<h2 id="heading-pattern-4-taming-multiple-api-contracts">Pattern 4: Taming Multiple API Contracts</h2>
<p>In a microservice world, each service defines its own API contract. The user service returns <code>firstName</code> and <code>lastName</code>. The order service returns <code>customerName</code> as a single string. The notification service expects <code>fullName</code>. Same concept, three different field names.</p>
<h3 id="heading-the-adapter-layer">The Adapter Layer</h3>
<p>Create an adapter layer that translates each service's response into a consistent domain model that your components use:</p>
<pre><code class="language-typescript">// Domain models: what the frontend actually works with
interface User {
  id: string;
  fullName: string;
  email: string;
  address: Address;
}

// Adapter for the User Service
function adaptUserServiceResponse(raw: UserServiceResponse): User {
  return {
    id: raw.userId,
    fullName: `\({raw.firstName} \){raw.lastName}`,
    email: raw.emailAddress,
    address: {
      line1: raw.address.street,
      city: raw.address.city,
      postcode: raw.address.zipCode,
      country: raw.address.countryCode,
    },
  };
}

// Adapter for the Order Service (which embeds a different user shape)
function adaptOrderCustomer(raw: OrderServiceCustomer): User {
  return {
    id: raw.customerId,
    fullName: raw.customerName,
    email: raw.email,
    address: {
      line1: raw.shippingAddress.addressLine1,
      city: raw.shippingAddress.city,
      postcode: raw.shippingAddress.postalCode,
      country: raw.shippingAddress.country,
    },
  };
}
</code></pre>
<p>Your components only work with the <code>User</code> type. They never see the raw service responses. When a service changes its API, you update one adapter, not every component that displays a user's name.</p>
<h3 id="heading-where-to-put-the-adapter-layer">Where to Put the Adapter Layer</h3>
<p>If you have a BFF, the adapters live there. The browser never sees the raw service response. If you're calling services directly from the frontend, place the adapters in your data-fetching layer, between the HTTP call and the cache:</p>
<pre><code class="language-typescript">// The adapter runs before data enters the cache
function useUser(userId: string) {
  return useQuery({
    queryKey: ["user", userId],
    queryFn: async () =&gt; {
      const raw = await fetch(`/api/users/${userId}`).then((r) =&gt; r.json());
      return adaptUserServiceResponse(raw);
    },
  });
}
</code></pre>
<h2 id="heading-pattern-5-timeout-budgets-for-page-assembly">Pattern 5: Timeout Budgets for Page Assembly</h2>
<p>When a page depends on multiple services, you need a timeout strategy. Without one, your page load time is determined by the slowest service, and in a microservice world, there's always a slow service.</p>
<p>A timeout budget allocates a maximum time for assembling all the data a page needs. If a non-critical service doesn't respond within its budget, you render without it.</p>
<p>In practice, this utility lives in a shared service layer (for example, <code>lib/api.ts</code>) rather than inline with each page's assembly logic. Here's the implementation:</p>
<pre><code class="language-typescript">// lib/api.ts: shared timeout utility
async function fetchWithTimeout&lt;T&gt;(
  url: string,
  options: RequestInit,
  timeoutMs: number
): Promise&lt;T | null&gt; {
  const controller = new AbortController();
  const timeout = setTimeout(() =&gt; controller.abort(), timeoutMs);

  try {
    const response = await fetch(url, {
      ...options,
      signal: controller.signal,
    });
    return response.json();
  } catch (error) {
    if (error instanceof DOMException &amp;&amp; error.name === "AbortError") {
      console.warn(`Request to \({url} timed out after \){timeoutMs}ms`);
    }
    return null;
  } finally {
    clearTimeout(timeout);
  }
}

// Page assembly with tiered timeouts
async function assembleProductPage(productId: string): Promise&lt;ProductPageData&gt; {
  // Critical data: longer timeout, page fails without it
  const product = await fetchWithTimeout&lt;Product&gt;(
    `/api/products/${productId}`,
    {},
    3000 // 3 second budget for critical data
  );

  if (!product) {
    throw new Error("Product not found");
  }

  // Non-critical data: shorter timeout, page renders without it
  const [reviews, recommendations, relatedProducts] = await Promise.all([
    fetchWithTimeout&lt;Review[]&gt;(
      `/api/reviews?productId=${productId}`,
      {},
      1500 // 1.5 second budget
    ),
    fetchWithTimeout&lt;Product[]&gt;(
      `/api/recommendations?productId=${productId}`,
      {},
      1000 // 1 second budget: nice to have
    ),
    fetchWithTimeout&lt;Product[]&gt;(
      `/api/products/${productId}/related`,
      {},
      1000
    ),
  ]);

  return {
    product,
    reviews: reviews ?? [],
    recommendations: recommendations ?? [],
    relatedProducts: relatedProducts ?? [],
  };
}
</code></pre>
<p>Notice the different budgets. Critical data (the product itself) gets 3 seconds. Non-critical data (reviews, recommendations) gets 1–1.5 seconds. If recommendations are slow, you show the product without them. The user doesn't wait for a service they may not even look at.</p>
<h2 id="heading-pattern-6-error-boundaries-per-service">Pattern 6: Error Boundaries Per Service</h2>
<p>React error boundaries are especially powerful in a microservice frontend. Instead of one error boundary at the page level, place boundaries around sections that map to different backend services.</p>
<p>If you haven't used error boundaries before, here's a minimal implementation. Error boundaries must be class components, React doesn't support them as function components yet (see the <a href="https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary">React docs</a> for more detail):</p>
<pre><code class="language-typescript">class ErrorBoundary extends React.Component&lt;
  { fallback: React.ReactNode; children: React.ReactNode },
  { hasError: boolean } &gt; {
  state = { hasError: false };

  static getDerivedStateFromError() {
    return { hasError: true };
  }

  componentDidCatch(error: Error, info: React.ErrorInfo) {
    console.error("ErrorBoundary caught:", error, info);
  }

  render() {
    if (this.state.hasError) return this.props.fallback;
    return this.props.children;
  }
}
</code></pre>
<p>With that in place, scope your boundaries to individual service sections:</p>
<pre><code class="language-typescript">function ProductPage({ productId }: { productId: string }) {
  return (
    &lt;div&gt;
      {/* If the product service fails, show a full-page error */}
      &lt;ErrorBoundary fallback={&lt;ProductErrorPage /&gt;}&gt;
        &lt;Suspense fallback={&lt;ProductSkeleton /&gt;}&gt;
          &lt;ProductDetails productId={productId} /&gt;
        &lt;/Suspense&gt;
      &lt;/ErrorBoundary&gt;

      {/* If the review service fails, just hide reviews */}
      &lt;ErrorBoundary fallback={&lt;EmptyState message="Reviews unavailable" /&gt;}&gt;
        &lt;Suspense fallback={&lt;ReviewSkeleton /&gt;}&gt;
          &lt;ProductReviews productId={productId} /&gt;
        &lt;/Suspense&gt;
      &lt;/ErrorBoundary&gt;

      {/* If recommendations fail, hide silently */}
      &lt;ErrorBoundary fallback={null}&gt;
        &lt;Suspense fallback={&lt;CarouselSkeleton /&gt;}&gt;
          &lt;Recommendations productId={productId} /&gt;
        &lt;/Suspense&gt;
      &lt;/ErrorBoundary&gt;
    &lt;/div&gt;
  );
}
</code></pre>
<p>Each boundary catches errors from its own data source independently. The review service crashing doesn't affect the product details. The recommendation service timing out doesn't show an error at all – the section simply doesn't render.</p>
<p>This maps directly to your critical/non-critical classification. Critical services get error boundaries with visible error UI. Non-critical services get boundaries that degrade silently or show a minimal empty state.</p>
<h2 id="heading-working-with-backend-teams-on-contracts">Working With Backend Teams on Contracts</h2>
<p>The technical patterns above solve symptoms. The root cause of most frontend pain in microservice environments is poor communication between frontend and backend teams about API contracts.</p>
<h3 id="heading-contract-conversations-to-have-early">Contract Conversations to Have Early</h3>
<h4 id="heading-1-what-fields-will-the-frontend-actually-use">1. What fields will the frontend actually use?</h4>
<p>Backend services often expose their entire data model. The frontend uses three fields. If the backend team knows which fields you depend on, they can maintain those fields more carefully and deprecate the ones nobody uses.</p>
<h4 id="heading-2-what-is-the-expected-latency-budget-for-this-endpoint">2. What is the expected latency budget for this endpoint?</h4>
<p>If the product page has a 2-second total budget and the recommendation service averages 1.8 seconds, you have a problem before you write any frontend code. Surface this early.</p>
<h4 id="heading-3-what-happens-when-this-service-is-degraded">3. What happens when this service is degraded?</h4>
<p>Ask each backend team: "If your service responds with 500 errors for an hour, what should the frontend show?" This question often reveals that nobody has thought about it, which is exactly why you need to ask.</p>
<h4 id="heading-4-how-will-you-communicate-breaking-changes">4. How will you communicate breaking changes?</h4>
<p>Agree on a process. Whether it is OpenAPI spec diffs in pull requests, a Slack channel for API changes, or versioned endpoints, pick something and hold each other to it.</p>
<h3 id="heading-api-contracts-as-shared-artifacts">API Contracts as Shared Artifacts</h3>
<p>Push for machine-readable contracts. OpenAPI specs, GraphQL schemas, or Protocol Buffer definitions serve as a shared source of truth between frontend and backend teams. They enable:</p>
<ul>
<li><p><strong>Automated type generation:</strong> Tools like <code>openapi-typescript</code> generate TypeScript types from OpenAPI specs. When the backend changes a field, your build fails immediately, not in production.</p>
</li>
<li><p><strong>Contract testing:</strong> Tools like <code>Pact</code> let you define the expected request/response pairs from the frontend's perspective. The backend runs these tests in their CI pipeline. If their changes break the frontend's expectations, the pipeline fails.</p>
</li>
<li><p><strong>Mock servers:</strong> Generated mocks from the spec let you build the frontend before the backend is ready. When the real service ships, your code already works.</p>
</li>
</ul>
<pre><code class="language-typescript">// Generated types from OpenAPI spec, always in sync with the backend
import type { components } from "./generated/inventory-api";

type Product = components["schemas"]["Product"];
type StockLevel = components["schemas"]["StockLevel"];

// If the backend renames "available" to "inStock",
// this code fails at compile time, not in production
function formatStockMessage(stock: StockLevel): string {
  if (stock.available &gt; 10) return "In Stock";
  if (stock.available &gt; 0) return `Only ${stock.available} left`;
  return "Out of Stock";
}
</code></pre>
<h3 id="heading-testing-against-multiple-services">Testing Against Multiple Services</h3>
<p>Contract testing catches backend-side breaking changes, but you also need to test your frontend's behavior when services respond in unexpected ways. <a href="https://mswjs.io/">Mock Service Worker (MSW)</a> lets you spin up per-service mock handlers in your test environment:</p>
<pre><code class="language-typescript">import { setupServer } from "msw/node";
import { http, HttpResponse } from "msw";

// Mock each service independently
const server = setupServer(
  http.get("/api/products/:id", () =&gt;
    HttpResponse.json({ productId: "abc-123", name: "Widget", price: 49.99 })
  ),
  http.get("/api/reviews", () =&gt;
    HttpResponse.json([{ rating: 5, body: "Great product" }])
  )
);

// Test: what happens when the review service is down?
test("renders product page when reviews service fails", async () =&gt; {
  server.use(
    http.get("/api/reviews", () =&gt; HttpResponse.error())
  );

  render(&lt;ProductPage productId="abc-123" /&gt;);

  expect(await screen.findByText("Widget")).toBeInTheDocument();
  expect(await screen.findByText("Reviews unavailable")).toBeInTheDocument();
});
</code></pre>
<p>This lets you simulate the partial failure scenarios from Pattern 2 in your test suite. Test your adapter layer (Pattern 4) with unit tests against raw service response fixtures, and use MSW for integration tests that verify the full page assembles correctly when individual services are slow, down, or return unexpected shapes.</p>
<h2 id="heading-when-to-push-back">When to Push Back</h2>
<p>Not every microservice problem has a frontend solution. Sometimes the right answer is to push back on the architecture.</p>
<p><strong>Push back when the frontend is making more than 5 API calls for a single page.</strong> This is a signal that either the services are too granular or there is a missing aggregation layer. The fix is a BFF or a composite API, not more <code>Promise.all</code> calls in the browser.</p>
<p><strong>Push back when two services return conflicting data about the same entity.</strong> If the user service says the user's name is "Jane" and the order service says it is "Janet," this is a data consistency problem that the frontend can't solve. It needs to be fixed at the source, either through event-driven syncing between services or by establishing one service as the authoritative source for that field.</p>
<p><strong>Push back when backend teams make breaking changes without notice.</strong> If your production app breaks because a service renamed a field in a minor version bump, that's a process failure. Advocate for versioned APIs, deprecation notices, and contract testing.</p>
<p>You're not just a consumer of APIs. You're a stakeholder in how those APIs are designed. The earlier you participate in API design conversations, the fewer surprises you deal with in production.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>The patterns in this article give you a structured starting point, but the underlying principle is consistent across all of them:</p>
<p>Key takeaways:</p>
<ol>
<li><p><strong>Own the aggregation layer:</strong> A BFF gives the frontend team control over response shapes and lets you handle partial failures at the server level instead of the browser.</p>
</li>
<li><p><strong>Classify every data source as critical or non-critical:</strong> This single decision determines your error handling, timeout budgets, and loading strategies for every section of every page.</p>
</li>
<li><p><strong>Normalize at the boundary:</strong> Adapter layers between raw service responses and your components protect you from upstream API changes and give you a consistent domain model.</p>
</li>
<li><p><strong>Invest in contracts:</strong> Machine-readable API contracts, generated types, and contract testing catch breaking changes at build time instead of in production.</p>
</li>
<li><p><strong>Push back when needed:</strong> Not every microservice problem has a frontend solution. If the architecture creates an unreasonable burden on the UI layer, say so early.</p>
</li>
</ol>
<p>Microservices are a backend architecture decision, but their consequences are felt most acutely in the frontend. The patterns in this article won't make that complexity disappear, but they will give you a structured way to manage it.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build Reusable Architecture for Large Next.js Applications ]]>
                </title>
                <description>
                    <![CDATA[ Every Next.js project starts the same way: you run npx create-next-app, write a few pages, maybe add an API route or two, and things feel clean. Then the project grows. Features multiply. A second app ]]>
                </description>
                <link>https://www.freecodecamp.org/news/reusable-architecture-for-large-nextjs-applications/</link>
                <guid isPermaLink="false">69d00029e466e2b762517489</guid>
                
                    <category>
                        <![CDATA[ Next.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ architecture ]]>
                    </category>
                
                    <category>
                        <![CDATA[ monorepo ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Abisoye Alli-Balogun ]]>
                </dc:creator>
                <pubDate>Fri, 03 Apr 2026 18:00:09 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/uploads/covers/5e1e335a7a1d3fcc59028c64/0a713a19-a418-4954-bfca-9b8bc1e77a03.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Every Next.js project starts the same way: you run <code>npx create-next-app</code>, write a few pages, maybe add an API route or two, and things feel clean.</p>
<p>Then the project grows. Features multiply. A second app appears, maybe a separate admin dashboard, a marketing site, or a mobile-facing API. Suddenly, you're copying components between repos, duplicating business logic, arguing over where auth utilities belong, and asking yourself: <em>where did it all go wrong?</em></p>
<p>The answer is almost always architecture, or rather, the absence of one. Not the kind that lives in a Notion doc but the kind baked into your folder structure, your module boundaries, and the tools you reach for at the start of a project (not after it's already broken).</p>
<p>This article is a practical guide to building layered, reusable architecture in Next.js.</p>
<p>You'll learn about the App Router's colocation model, building scalable folder structures around features, sharing logic across apps with Turborepo, drawing clean data-fetching boundaries using Server Components, designing a testing strategy that matches your layer structure, and wiring up a CI/CD pipeline that only builds and tests what actually changed.</p>
<p>By the end, you'll have a blueprint you can actually use, not just admire.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a href="#heading-the-core-problem-coupling-without-intention">The Core Problem: Coupling Without Intention</a></p>
</li>
<li><p><a href="#heading-layer-1-the-app-router-and-colocation">Layer 1: The App Router and Colocation</a></p>
</li>
<li><p><a href="#heading-layer-2-feature-based-folder-structure">Layer 2: Feature-Based Folder Structure</a></p>
</li>
<li><p><a href="#heading-layer-3-monorepo-with-turborepo-sharing-logic-across-apps">Layer 3: Monorepo with Turborepo (Sharing Logic Across Apps)</a></p>
</li>
<li><p><a href="#heading-layer-4-server-components-and-data-fetching-boundaries">Layer 4: Server Components and Data-Fetching Boundaries</a></p>
</li>
<li><p><a href="#heading-layer-5-testing-strategy-for-a-layered-codebase">Layer 5: Testing Strategy for a Layered Codebase</a></p>
</li>
<li><p><a href="#heading-layer-6-cicd-with-turborepo">Layer 6: CI/CD with Turborepo</a></p>
</li>
<li><p><a href="#heading-putting-it-all-together-the-full-blueprint">Putting It All Together: The Full Blueprint</a></p>
</li>
<li><p><a href="#heading-common-pitfalls-and-how-to-avoid-them">Common Pitfalls and How to Avoid Them</a></p>
</li>
<li><p><a href="#heading-final-thoughts">Final Thoughts</a></p>
</li>
</ul>
<h2 id="heading-the-core-problem-coupling-without-intention">The Core Problem: Coupling Without Intention</h2>
<p>When a component reaches directly into a global store, when a page imports a utility from three directories away, when your auth logic is spread across <code>/lib</code>, <code>/helpers</code>, and <code>/utils</code> with no clear owner, every file knows too much about every other file.</p>
<p>The app still runs. But now changing one thing breaks three others, onboarding takes a week, and adding a second app means copying half the first one.</p>
<p>Layered architecture solves this by giving everything a place, and making those places mean something.</p>
<h2 id="heading-layer-1-the-app-router-and-colocation">Layer 1: The App Router and Colocation</h2>
<p>Next.js 13+ introduced the App Router with a file-system-based routing model that does something subtly powerful: it lets you colocate everything related to a route <em>inside</em> that route's folder.</p>
<p>Before the App Router, pages lived in <code>/pages</code>, components lived in <code>/components</code>, and data fetching was scattered. The App Router flips this. A route segment can now own its layout, its loading and error states, its server actions, and even its local components, all in one place.</p>
<h3 id="heading-what-colocation-actually-means">What Colocation Actually Means</h3>
<p>Consider a <code>/dashboard</code> route. In the App Router model, its folder might look like this:</p>
<pre><code class="language-plaintext">app/
  dashboard/
    page.tsx              # The route entry point
    layout.tsx            # Dashboard-specific shell/navigation
    loading.tsx           # Streaming loading state
    error.tsx             # Error boundary
    components/
      StatsCard.tsx       # Used only within dashboard
      ActivityFeed.tsx
    lib/
      queries.ts          # Data fetching for this route only
      formatters.ts       # Dashboard-specific transforms
</code></pre>
<p>The key insight: <code>StatsCard.tsx</code> and <code>queries.ts</code> don't belong to your whole application, they belong to <code>/dashboard</code>. When you delete or refactor the dashboard, you delete or refactor one folder. Nothing else breaks.</p>
<p>This is colocation. It's not a new idea, but the App Router makes it idiomatic in Next.js for the first time.</p>
<h3 id="heading-the-rule-of-proximity">The Rule of Proximity</h3>
<p>A good heuristic: <em>a file should live as close as possible to where it's used.</em> If it's used in one route, it lives in that route's folder. If it's used by two routes under the same parent segment, it moves up one level. If it's used across the entire app, it belongs in a shared layer (more on that shortly).</p>
<pre><code class="language-plaintext">app/
  (marketing)/          # Route group , no URL segment
    layout.tsx          # Shared layout for marketing pages
    page.tsx
    about/
      page.tsx
  (dashboard)/
    layout.tsx          # Different shell for app routes
    dashboard/
      page.tsx
    settings/
      page.tsx
</code></pre>
<p>Route groups (folders wrapped in parentheses) let you share layouts across segments without polluting the URL. This is a clean way to separate concerns, marketing pages and app pages can have entirely different shells without any URL trickery.</p>
<h2 id="heading-layer-2-feature-based-folder-structure">Layer 2: Feature-Based Folder Structure</h2>
<p>Colocation handles the route level. But large applications have cross-cutting concerns – things that don't belong to any single route but aren't generic utilities either.</p>
<p>This is where most projects fall apart: the <code>/components</code> folder becomes a dumping ground, <code>/lib</code> becomes a junk drawer, and nobody agrees on where <code>useAuth</code> should live.</p>
<p>Feature-based folder structure brings order to this chaos.</p>
<h3 id="heading-organising-by-domain-not-by-file-type">Organising by Domain, Not by File Type</h3>
<p>Instead of grouping files by what they <em>are</em> (components, hooks, utils), group them by what they <em>do</em>.</p>
<pre><code class="language-plaintext">src/
  features/
    auth/
      components/
        LoginForm.tsx
        AuthGuard.tsx
      hooks/
        useAuth.ts
        useSession.ts
      lib/
        tokenStorage.ts
        validators.ts
      types.ts
      index.ts            # Public API , only export what others need

    billing/
      components/
        PricingTable.tsx
        SubscriptionBadge.tsx
      hooks/
        useSubscription.ts
      lib/
        stripe.ts
      types.ts
      index.ts

    notifications/
      ...
</code></pre>
<p>Each feature folder is a self-contained unit. It has its own components, hooks, utilities, and types. Crucially, it has a barrel file (<code>index.ts</code>) that defines its <em>public API</em>, the things other parts of the app are allowed to import.</p>
<h3 id="heading-enforcing-boundaries-with-barrel-exports">Enforcing Boundaries with Barrel Exports</h3>
<p>The <code>index.ts</code> is not optional. It's the mechanism that prevents features from becoming entangled.</p>
<pre><code class="language-typescript">// features/auth/index.ts
export { LoginForm } from './components/LoginForm';
export { AuthGuard } from './components/AuthGuard';
export { useAuth } from './hooks/useAuth';
export type { AuthUser, AuthState } from './types';

// NOT exported, internal implementation detail:
// tokenStorage.ts, validators.ts
</code></pre>
<p>Now, the rest of your app imports from <code>@/features/auth</code>, never from <code>@/features/auth/lib/tokenStorage</code>. If you refactor how tokens are stored internally, nothing outside the feature breaks. This is the essence of encapsulation, not just as a theoretical principle, but as a structural one enforced by your folder layout.</p>
<h3 id="heading-shared-vs-feature">Shared vs. Feature</h3>
<p>Not everything belongs in a feature. Truly generic utilities: a <code>cn()</code> classname helper, a date formatter, or a base HTTP client, for example, belong in a shared layer:</p>
<pre><code class="language-plaintext">src/
  shared/
    components/
      Button.tsx
      Modal.tsx
      Spinner.tsx
    hooks/
      useDebounce.ts
      useMediaQuery.ts
    lib/
      http.ts
      dates.ts
    ui/              # shadcn/ui or design system components
</code></pre>
<p>The rule: <code>shared/</code> has zero knowledge of any feature. Features can import from <code>shared/</code>. <code>shared/</code> never imports from a feature.</p>
<h2 id="heading-layer-3-monorepo-with-turborepo-sharing-logic-across-apps">Layer 3: Monorepo with Turborepo (Sharing Logic Across Apps)</h2>
<p>Single-repo architecture gets you far, but most teams eventually end up with multiple apps: a customer-facing Next.js app, an admin panel, a separate marketing site, maybe a set of API services.</p>
<p>The question becomes: <em>how do you share code between them without copy-pasting?</em></p>
<p>The answer is a monorepo with shared packages, and Turborepo is currently the best tool for Next.js teams doing this.</p>
<h3 id="heading-the-monorepo-shape">The Monorepo Shape</h3>
<p>A well-structured Turborepo looks like this:</p>
<pre><code class="language-plaintext">my-platform/
  apps/
    web/              # Customer-facing Next.js app
    admin/            # Internal admin panel (also Next.js)
    marketing/        # Marketing site
  packages/
    ui/               # Shared component library
    config/           # Shared ESLint, TypeScript, Tailwind configs
    auth/             # Shared auth utilities and types
    database/         # Prisma client + query helpers
    utils/            # Generic utilities
  turbo.json
  package.json        # Root workspace config
</code></pre>
<p><code>apps/</code> contains deployable applications. <code>packages/</code> contains shared code that apps depend on. Neither app imports directly from the other, all sharing flows through <code>packages/</code>.</p>
<h3 id="heading-setting-up-a-shared-package">Setting Up a Shared Package</h3>
<p>A package is just a folder with a <code>package.json</code> that other workspace members can depend on.</p>
<pre><code class="language-json">// packages/ui/package.json
{
  "name": "@my-platform/ui",
  "version": "0.0.1",
  "main": "./src/index.ts",
  "types": "./src/index.ts",
  "exports": {
    ".": "./src/index.ts"
  }
}
</code></pre>
<pre><code class="language-typescript">// packages/ui/src/index.ts
export { Button } from './Button';
export { Modal } from './Modal';
export { Card } from './Card';
</code></pre>
<p>Now your apps consume it like any npm package:</p>
<pre><code class="language-json">// apps/web/package.json
{
  "dependencies": {
    "@my-platform/ui": "*"
  }
}
</code></pre>
<pre><code class="language-tsx">// apps/web/app/dashboard/page.tsx
import { Card, Button } from '@my-platform/ui';
</code></pre>
<p>Change <code>Card</code> once in <code>packages/ui</code>, and every app that uses it gets the update, no copy-pasting, no drift.</p>
<p><strong>Important:</strong> Because the package points directly at TypeScript source files (not compiled output), each consuming Next.js app must tell the bundler to transpile it. Add this to your Next.js config:</p>
<pre><code class="language-ts">// apps/web/next.config.ts
const config: import('next').NextConfig = {
  transpilePackages: ['@my-platform/ui', '@my-platform/auth', '@my-platform/utils'],
};

export default config;
</code></pre>
<p>Without this, the build fails with syntax errors, Next.js doesn't transpile packages from <code>node_modules</code> or workspace dependencies by default. The alternative is compiling each package to <code>dist/</code> and pointing <code>exports</code> there, but that adds a build step to every package and slows down the dev feedback loop. For internal monorepo packages, <code>transpilePackages</code> is the simpler tradeoff.</p>
<h3 id="heading-the-turbojson-pipeline">The <code>turbo.json</code> Pipeline</h3>
<p>Turborepo's real power is its build pipeline. It understands the dependency graph between your packages and apps, caches build outputs, and runs tasks in parallel where possible.</p>
<pre><code class="language-json">// turbo.json
{
  "$schema": "https://turbo.build/schema.json",
  "tasks": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": [".next/**", "dist/**"]
    },
    "lint": {
      "outputs": []
    },
    "dev": {
      "cache": false,
      "persistent": true
    },
    "type-check": {
      "dependsOn": ["^build"],
      "outputs": []
    }
  }
}
</code></pre>
<p>The <code>^build</code> syntax means: <em>before building this package, build all its dependencies first.</em> So if <code>apps/web</code> depends on <code>packages/ui</code>, Turborepo ensures <code>packages/ui</code> is built before <code>apps/web</code> starts. Remote caching means if <code>packages/ui</code> hasn't changed, Turborepo skips rebuilding it entirely, even across CI runs and team members' machines.</p>
<h3 id="heading-what-goes-in-a-package-vs-an-app">What Goes in a Package vs. an App</h3>
<p>A useful litmus test:</p>
<table>
<thead>
<tr>
<th>Lives in <code>packages/</code></th>
<th>Lives in <code>apps/</code></th>
</tr>
</thead>
<tbody><tr>
<td>Design system / UI primitives</td>
<td>Route definitions</td>
</tr>
<tr>
<td>Auth utilities and types</td>
<td>App-specific layouts</td>
</tr>
<tr>
<td>Database client and queries</td>
<td>Feature-specific pages</td>
</tr>
<tr>
<td>Shared TypeScript configs</td>
<td>API route handlers</td>
</tr>
<tr>
<td>Analytics abstractions</td>
<td>Environment-specific config</td>
</tr>
<tr>
<td>Generic hooks (useDebounce)</td>
<td>App-specific business logic</td>
</tr>
</tbody></table>
<p>If two apps need the same logic, it goes in a package. If only one app needs it, it stays in that app, even if you <em>think</em> the other app might need it someday. Premature abstraction is just as damaging as none at all.</p>
<h2 id="heading-layer-4-server-components-and-data-fetching-boundaries">Layer 4: Server Components and Data-Fetching Boundaries</h2>
<p>The App Router's Server Components model is arguably the most architecturally significant change Next.js has ever shipped, and also the most misunderstood.</p>
<p>Most developers approach it as a performance optimisation. It is that, but it's more importantly an <em>architectural boundary</em>. Understanding where that boundary sits, and designing around it deliberately, is what separates scalable App Router codebases from ones that fight the framework.</p>
<h3 id="heading-the-mental-model-two-worlds">The Mental Model: Two Worlds</h3>
<p>Every component in the App Router lives in one of two worlds:</p>
<p><strong>Server Components</strong> (default) run exclusively on the server. They can <code>await</code> data directly, access databases, read environment variables, and reduce the JavaScript sent to the browser. They can't use browser APIs, <code>useState</code>, <code>useEffect</code>, or event handlers.</p>
<p><strong>Client Components</strong> (<code>'use client'</code>) run in the browser (and also during SSR/hydration). They can use hooks, handle events, and access browser APIs. They can't directly <code>await</code> server-side resources.</p>
<p>The directive <code>'use client'</code> doesn't mean <em>"this runs only in the browser"</em> , it means <em>"this is the boundary where the server-to-client handoff begins."</em> Any module <em>imported</em> by a Client Component becomes part of the client bundle.</p>
<p>But Server Components <em>passed as props</em> (typically via <code>children</code>) retain their server-only nature, they're rendered on the server and streamed as HTML, not included in the client bundle. This distinction is what makes the composition pattern below work.</p>
<h3 id="heading-designing-the-boundary">Designing the Boundary</h3>
<p>The goal is to push the <code>'use client'</code> boundary as far down the tree as possible, keeping data fetching and heavy logic on the server, and reserving Client Components for genuinely interactive leaves.</p>
<p>A pattern that works well in practice:</p>
<pre><code class="language-tsx">// app/dashboard/page.tsx , Server Component
// Fetches data, no 'use client' directive needed

import { getMetrics } from '@/features/analytics/lib/queries';
import { MetricsDashboard } from './components/MetricsDashboard';

export default async function DashboardPage() {
  const metrics = await getMetrics();   // Direct DB call , no API round-trip
  return &lt;MetricsDashboard data={metrics} /&gt;;
}
</code></pre>
<pre><code class="language-tsx">// app/dashboard/components/MetricsDashboard.tsx , Server Component
// Composes layout, delegates interactivity to leaves

import { StatsCard } from './StatsCard';
import { ChartSection } from './ChartSection';

export function MetricsDashboard({ data }) {
  return (
    &lt;div className="grid gap-6"&gt;
      &lt;StatsCard value={data.revenue} label="Revenue" /&gt;
      &lt;ChartSection points={data.trend} /&gt;
    &lt;/div&gt;
  );
}
</code></pre>
<pre><code class="language-tsx">// app/dashboard/components/ChartSection.tsx , Client Component
// Interactive chart needs browser APIs

'use client';

import { useState } from 'react';
import { LineChart, RangeSelector } from '@my-platform/ui';

export function ChartSection({ points }) {
  const [range, setRange] = useState('7d');
  return (
    &lt;div&gt;
      &lt;RangeSelector value={range} onChange={setRange} /&gt;
      &lt;LineChart data={points.filter(/* range logic */)} /&gt;
    &lt;/div&gt;
  );
}
</code></pre>
<p>The data flows from server to client in one direction. The server does the expensive work (database query), passes serialisable data down as props, and the client receives a ready-to-render dataset – no loading spinners, no client-side fetch waterfalls.</p>
<h3 id="heading-colocating-data-fetching-with-routes">Colocating Data Fetching with Routes</h3>
<p>A powerful pattern enabled by Server Components is colocating data fetching directly with the route that needs it, eliminating the need for global state management in many cases.</p>
<pre><code class="language-plaintext">app/
  orders/
    page.tsx              # await getOrders() , renders list
    [id]/
      page.tsx            # await getOrder(id) , renders single order
      loading.tsx         # Streaming skeleton while awaiting
      components/
        OrderTimeline.tsx  # Server Component , renders timeline data
        CancelButton.tsx  # 'use client' , needs click handler
</code></pre>
<p>Each page fetches its own data, scoped to what it needs. Nested layouts and pages can fetch concurrently when using <code>Promise.all</code> or parallel route segments. And <code>loading.tsx</code> gives you streaming suspense boundaries without writing a single <code>&lt;Suspense&gt;</code> wrapper manually.</p>
<h3 id="heading-when-to-use-a-fetch-layer-vs-direct-queries">When to Use a Fetch Layer vs. Direct Queries</h3>
<p>As apps scale, you'll want a consistent approach to data access. A practical pattern:</p>
<pre><code class="language-typescript">// packages/database/src/queries/orders.ts
// Runs on the server , can be imported in any Server Component

import { db } from '../client';

export async function getOrdersByUser(userId: string) {
  return db.order.findMany({
    where: { userId },
    include: { items: true },
    orderBy: { createdAt: 'desc' },
  });
}
</code></pre>
<pre><code class="language-typescript">// packages/database/src/index.ts
export { getOrdersByUser } from './queries/orders';
export { getProductById } from './queries/products';
// ...
</code></pre>
<p>Your Server Components import from <code>@my-platform/database</code>. Your Client Components never touch this package: they call API routes or Server Actions if they need to mutate data. This keeps the boundary clean and auditable.</p>
<h3 id="heading-server-actions-for-mutations">Server Actions for Mutations</h3>
<p>Data fetching flows through Server Components, but mutations need their own boundary. Server Actions (<code>'use server'</code>) let you define server-side functions that Client Components can call directly – no API route boilerplate needed.</p>
<pre><code class="language-typescript">// app/orders/[id]/actions.ts
'use server';

import { db } from '@my-platform/database';
import { revalidatePath } from 'next/cache';

export async function cancelOrder(orderId: string) {
  await db.order.update({
    where: { id: orderId },
    data: { status: 'cancelled', cancelledAt: new Date() },
  });

  revalidatePath(`/orders/${orderId}`);
}
</code></pre>
<pre><code class="language-tsx">// app/orders/[id]/components/CancelButton.tsx
'use client';

import { cancelOrder } from '../actions';
import { useTransition } from 'react';

export function CancelButton({ orderId }: { orderId: string }) {
  const [isPending, startTransition] = useTransition();

  return (
    &lt;button
      disabled={isPending}
      onClick={() =&gt; startTransition(() =&gt; cancelOrder(orderId))}
    &gt;
      {isPending ? 'Cancelling...' : 'Cancel Order'}
    &lt;/button&gt;
  );
}
</code></pre>
<p>The architectural decision:</p>
<ul>
<li><p><strong>use Server Actions for mutations that are colocated with a specific route</strong> (cancelling an order, updating a profile).</p>
</li>
<li><p><strong>Use API routes for mutations that are consumed by external clients</strong> (webhooks, mobile apps, third-party integrations).</p>
</li>
</ul>
<p>Server Actions keep mutation logic close to the UI that triggers it. API routes provide a stable contract for external consumers.</p>
<p>This completes the data flow picture: Server Components handle reads, Server Actions handle writes, and Client Components are the interactive surface that connects them.</p>
<h2 id="heading-layer-5-testing-strategy-for-a-layered-codebase">Layer 5: Testing Strategy for a Layered Codebase</h2>
<p>The testing pyramid is one of those concepts that sounds obvious in theory but falls apart in practice, usually because the codebase doesn't have clear boundaries to test against. When everything is tangled, every test becomes an integration test by accident.</p>
<p>The layered architecture you've built changes this: each layer has a defined surface area, so you can test each one at the right level of abstraction.</p>
<h3 id="heading-test-each-layer-at-the-right-granularity">Test Each Layer at the Right Granularity</h3>
<p>The layered architecture maps naturally onto the testing pyramid:</p>
<table>
<thead>
<tr>
<th>Layer</th>
<th>Test Type</th>
<th>Tools</th>
</tr>
</thead>
<tbody><tr>
<td><code>packages/</code> (utils, db queries)</td>
<td>Unit tests</td>
<td>Vitest</td>
</tr>
<tr>
<td><code>features/</code> (hooks, lib, components)</td>
<td>Unit + Integration</td>
<td>Vitest + React Testing Library</td>
</tr>
<tr>
<td>App Router pages (Server Components)</td>
<td>Integration</td>
<td>Vitest + custom render</td>
</tr>
<tr>
<td>Critical user flows (checkout, auth)</td>
<td>End-to-end</td>
<td>Playwright</td>
</tr>
</tbody></table>
<p>The goal: test shared packages exhaustively, test features thoroughly, test pages for integration correctness, and use E2E only for the flows that matter most.</p>
<p>Not everything needs an E2E test, and treating E2E as the default testing strategy is one of the most expensive mistakes a team can make.</p>
<h3 id="heading-unit-testing-shared-packages">Unit Testing Shared Packages</h3>
<p>Packages in <code>packages/</code> are the easiest to test. They're pure TypeScript with no framework coupling. Use Vitest:</p>
<pre><code class="language-typescript">// packages/utils/src/dates.test.ts
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import { formatRelativeDate } from './dates';

describe('formatRelativeDate', () =&gt; {
  beforeEach(() =&gt; {
    // Pin the clock to avoid flaky results near midnight
    vi.useFakeTimers();
    vi.setSystemTime(new Date('2026-03-15T12:00:00Z'));
  });

  afterEach(() =&gt; {
    vi.useRealTimers();
  });

  it('returns "today" for dates within the current day', () =&gt; {
    expect(formatRelativeDate(new Date())).toBe('today');
  });

  it('returns "yesterday" for dates on the previous day', () =&gt; {
    const yesterday = new Date('2026-03-14T15:00:00Z');
    expect(formatRelativeDate(yesterday)).toBe('yesterday');
  });
});
</code></pre>
<p>Keep package tests colocated with the source file. A <code>dates.ts</code> file has a <code>dates.test.ts</code> sibling. No separate <code>__tests__</code> folders, those are relics of less structured codebases.</p>
<h3 id="heading-testing-feature-modules">Testing Feature Modules</h3>
<p>Features are where most of your business logic lives, so they get the most test coverage. The key rule: test the public API of the feature, not its internals.</p>
<pre><code class="language-typescript">// features/auth/hooks/useAuth.test.ts
import { renderHook, act } from '@testing-library/react';
import { useAuth } from '../hooks/useAuth';
import { createWrapper } from '@/test/utils'; // your test provider wrapper

describe('useAuth', () =&gt; {
  it('returns authenticated state when session exists', async () =&gt; {
    const { result } = renderHook(() =&gt; useAuth(), {
      wrapper: createWrapper({ session: mockSession }),
    });

    expect(result.current.isAuthenticated).toBe(true);
    expect(result.current.user.email).toBe(mockSession.user.email);
  });

  it('redirects to login when session is null', async () =&gt; {
    const { result } = renderHook(() =&gt; useAuth(), {
      wrapper: createWrapper({ session: null }),
    });

    expect(result.current.isAuthenticated).toBe(false);
  });
});
</code></pre>
<p>Notice that the test imports from the hook directly, not from the feature's <code>index.ts</code> barrel. Feature index exports are public APIs. They're tested through integration tests that consume the feature as a whole. Internal hooks and utilities are tested at the unit level. Both are valid, and the distinction is intentional.</p>
<h3 id="heading-testing-server-components">Testing Server Components</h3>
<p>Server Components are async functions that return JSX. Testing them directly is still an evolving story. React's test renderer doesn't natively handle async components, and calling <code>await DashboardPage()</code> then passing the result to <code>render()</code> produces subtle issues (missing context, <code>act()</code> warnings, or outright failures depending on your setup).</p>
<p>The most reliable approach today is to <strong>test the layers separately</strong>: mock the data layer to verify it's called correctly, and test the presentational component with static props.</p>
<pre><code class="language-typescript">// app/dashboard/components/MetricsDashboard.test.tsx
import { describe, it, expect } from 'vitest';
import { render, screen } from '@testing-library/react';
import { MetricsDashboard } from './MetricsDashboard';

describe('MetricsDashboard', () =&gt; {
  it('renders revenue metric from provided data', () =&gt; {
    render(
      &lt;MetricsDashboard data={{ revenue: 84200, trend: [] }} /&gt;
    );

    expect(screen.getByText('£84,200')).toBeInTheDocument();
  });
});
</code></pre>
<pre><code class="language-typescript">// features/analytics/lib/queries.test.ts
import { describe, it, expect } from 'vitest';
import { getMetrics } from './queries';

describe('getMetrics', () =&gt; {
  it('returns revenue and trend data', async () =&gt; {
    const metrics = await getMetrics();

    expect(metrics.revenue).toBeGreaterThan(0);
    expect(Array.isArray(metrics.trend)).toBe(true);
  });
});
</code></pre>
<p>The key insight: mock at the data layer boundary, not at the database or network layer. The data query has its own tests in <code>packages/database</code>. The presentational component has its own tests with static props. The Server Component page wires them together, and that wiring is verified by your E2E tests, which are better suited to catching integration issues across the async boundary.</p>
<h3 id="heading-end-to-end-tests-with-playwright">End-to-End Tests with Playwright</h3>
<p>Reserve Playwright for the flows that touch multiple layers and where a breakage would be catastrophic: authentication, checkout, and form submission with side effects. Don't use it for visual regressions or static content, as that's expensive and slow.</p>
<pre><code class="language-typescript">// e2e/auth.spec.ts
import { test, expect } from '@playwright/test';

test('user can log in and reach dashboard', async ({ page }) =&gt; {
  await page.goto('/login');
  await page.fill('[name="email"]', 'test@example.com');
  await page.fill('[name="password"]', 'password123');
  await page.click('button[type="submit"]');

  await expect(page).toHaveURL('/dashboard');
  await expect(page.getByRole('heading', { name: 'Dashboard' })).toBeVisible();
});
</code></pre>
<p>Colocate E2E tests in a top-level <code>e2e/</code> folder at the monorepo root. They span apps and don't belong inside any single app's directory.</p>
<h3 id="heading-configuring-vitest-across-the-monorepo">Configuring Vitest Across the Monorepo</h3>
<p>Each package and app has its own <code>vitest.config.ts</code>, but they can share a base config via a shared package:</p>
<pre><code class="language-typescript">// packages/config/vitest.base.ts
import { defineConfig } from 'vitest/config';

export default defineConfig({
  test: {
    environment: 'jsdom',
    globals: true,
    setupFiles: ['./src/test/setup.ts'],
    coverage: {
      provider: 'v8',
      reporter: ['text', 'lcov'],
    },
  },
});
</code></pre>
<pre><code class="language-typescript">// apps/web/vitest.config.ts
import { mergeConfig } from 'vitest/config';
import base from '@my-platform/config/vitest.base';

export default mergeConfig(base, {
  test: {
    include: ['src/**/*.test.{ts,tsx}', 'app/**/*.test.{ts,tsx}'],
  },
});
</code></pre>
<p>This ensures consistent test configuration across every app and package without duplication.</p>
<h2 id="heading-layer-6-cicd-with-turborepo">Layer 6: CI/CD with Turborepo</h2>
<p>A well-designed monorepo without a smart CI pipeline is just a big repo. Turborepo's real power emerges in CI, where it can cut build and test times dramatically through caching and intelligent task scheduling.</p>
<h3 id="heading-the-core-insight-only-run-what-changed">The Core Insight: Only Run What Changed</h3>
<p>Traditional CI pipelines run everything on every commit. In a monorepo, this means running tests for <code>apps/admin</code> when you only changed a utility in <code>apps/web</code>. Turborepo's dependency graph awareness eliminates this.</p>
<p>When you run <code>turbo test</code>, Turborepo:</p>
<ol>
<li><p>Builds the dependency graph from your <code>package.json</code> files</p>
</li>
<li><p>Checks which packages have changed (against the last cached state)</p>
</li>
<li><p>Runs tests only for changed packages and their dependents</p>
</li>
<li><p>Caches results. If nothing changed, it restores from cache instantly.</p>
</li>
</ol>
<p>A change to <code>packages/ui</code> triggers tests for <code>packages/ui</code>, <code>apps/web</code>, and <code>apps/admin</code> (since both depend on it). A change only to <code>apps/web</code> triggers tests for <code>apps/web</code> only.</p>
<h3 id="heading-remote-caching">Remote Caching</h3>
<p>Without remote caching, Turborepo's local cache doesn't help in CI – each run starts fresh. With remote caching, build and test artifacts are stored in the cloud and shared across all CI runners and developers' machines.</p>
<pre><code class="language-bash"># Authenticate with Turborepo remote cache (Vercel)
npx turbo login
npx turbo link
</code></pre>
<p>Or use a self-hosted cache server if you need to keep artifacts on your own infrastructure. Once configured, a CI run on a branch that touched only <code>apps/web</code> might take 45 seconds instead of 8 minutes, because every <code>packages/*</code> task restores from cache.</p>
<h3 id="heading-a-production-ready-github-actions-pipeline">A Production-Ready GitHub Actions Pipeline</h3>
<p>Here's a complete pipeline that uses Turborepo's caching, runs affected tasks only, and splits lint, test, and build into parallel jobs:</p>
<pre><code class="language-yaml"># .github/workflows/ci.yml
name: CI

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

env:
  TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
  TURBO_TEAM: ${{ secrets.TURBO_TEAM }}

jobs:
  lint:
    name: Lint
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'npm'

      - run: npm ci
      - run: npx turbo lint --filter="...[origin/main]"

  test:
    name: Test
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'npm'

      - run: npm ci
      - run: npx turbo test --filter="...[origin/main]"

  build:
    name: Build
    runs-on: ubuntu-latest
    needs: [lint, test]
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'npm'

      - run: npm ci
      - run: npx turbo build --filter="...[origin/main]"

  e2e:
    name: E2E Tests
    runs-on: ubuntu-latest
    needs: [build]
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'npm'

      - run: npm ci
      - run: npx playwright install --with-deps

      - name: Build the app (restores from Turborepo cache if unchanged)
        run: npx turbo build --filter="apps/web"

      - name: Run E2E tests
        run: npx turbo e2e
</code></pre>
<p>The E2E job assumes Playwright's <code>webServer</code> config handles starting the app automatically. Configure this in your <code>playwright.config.ts</code>:</p>
<pre><code class="language-typescript">// playwright.config.ts
export default defineConfig({
  webServer: {
    command: 'npm run start --prefix apps/web',
    port: 3000,
    reuseExistingServer: !process.env.CI,
  },
});
</code></pre>
<p>This way Playwright starts the production server before tests run and tears it down afterwards – no manual server management in CI.</p>
<p>The <code>--filter="...[origin/main]"</code> flag is the critical piece. It tells Turborepo to run tasks only for packages that have changed since the <code>main</code> branch, plus all packages that depend on those changed packages. This is the most impactful optimisation in the whole pipeline.</p>
<h3 id="heading-filtering-strategies">Filtering Strategies</h3>
<p>Turborepo's <code>--filter</code> flag is flexible and worth understanding:</p>
<pre><code class="language-bash"># Only run tasks for packages that changed vs main
turbo test --filter="...[origin/main]"

# Run tasks for a specific app and all its dependencies
turbo build --filter="apps/web..."

# Run tasks for everything except a specific app
turbo test --filter="!apps/admin"

# Run tasks for all apps (not packages)
turbo build --filter="./apps/*"
</code></pre>
<p>For most CI pipelines, <code>--filter="...[origin/main]"</code> on feature branches and <code>turbo run test build</code> (no filter) on <code>main</code> merges is the right split. You want fast feedback on PRs and confidence that everything still works on main.</p>
<h3 id="heading-deployment-pipeline-with-per-app-filtering">Deployment Pipeline with Per-App Filtering</h3>
<p>When deploying to Vercel, Netlify, or any platform with per-app deployments, Turborepo lets you detect which apps actually changed and skip deployments for unchanged ones:</p>
<pre><code class="language-yaml"># .github/workflows/deploy.yml
- name: Check if web app changed
  id: check-web
  run: |
    CHANGED=$(npx turbo run build --filter="apps/web...[origin/main]" --dry=json | jq '.packages | length')
    echo "changed=\(CHANGED" &gt;&gt; \)GITHUB_OUTPUT

- name: Deploy web
  if: steps.check-web.outputs.changed != '0'
  run: vercel deploy --prod
  env:
    VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
</code></pre>
<p>This ensures your admin app doesn't trigger a deployment when only the marketing site changed, reducing deploy times, costs, and the blast radius of any deployment failure.</p>
<h3 id="heading-environment-variable-management">Environment Variable Management</h3>
<p>One of the trickier parts of a monorepo CI setup is environment variables: each app needs its own secrets, but some are shared across apps.</p>
<p>A clean convention:</p>
<pre><code class="language-plaintext"># .env (repo root , shared across all apps in local dev)
DATABASE_URL=...
REDIS_URL=...

# apps/web/.env.local (web-specific overrides)
NEXT_PUBLIC_APP_URL=https://app.example.com
STRIPE_KEY=...

# apps/admin/.env.local (admin-specific)
NEXT_PUBLIC_APP_URL=https://admin.example.com
ADMIN_SECRET=...
</code></pre>
<p>In CI, store shared secrets as organisation-level GitHub secrets and app-specific secrets as repository-level secrets scoped to the appropriate environment.</p>
<p>Never store secrets in <code>turbo.json</code> or any committed file. Instead, use <code>env</code> in your pipeline steps and Turborepo's <code>globalEnv</code> field in <code>turbo.json</code> to declare which env vars should bust the cache when they change:</p>
<pre><code class="language-json">// turbo.json
{
  "globalEnv": ["NODE_ENV", "DATABASE_URL"],
  "tasks": {
    "build": {
      "env": ["NEXT_PUBLIC_APP_URL", "STRIPE_KEY"],
      "dependsOn": ["^build"],
      "outputs": [".next/**"]
    }
  }
}
</code></pre>
<p>This tells Turborepo: if <code>DATABASE_URL</code> changes, invalidate the cache for all tasks. If <code>NEXT_PUBLIC_APP_URL</code> changes, only invalidate the <code>build</code> task. Without this, you risk Turborepo restoring a cached build that was compiled against a different environment, a subtle and painful bug.</p>
<h2 id="heading-putting-it-all-together-the-full-blueprint">Putting It All Together: The Full Blueprint</h2>
<p>Here's what the complete architecture looks like assembled:</p>
<pre><code class="language-plaintext">my-platform/
  apps/
    web/
      app/
        (marketing)/
          layout.tsx
          page.tsx
          about/page.tsx
        (app)/
          layout.tsx            # Auth-protected shell
          dashboard/
            page.tsx            # Server Component , fetches data
            loading.tsx
            components/
              MetricsDashboard.tsx
              ChartSection.tsx  # 'use client'
          orders/
            page.tsx
            [id]/
              page.tsx
              components/
                OrderTimeline.tsx
                CancelButton.tsx  # 'use client'
      src/
        features/
          auth/
            components/
            hooks/
            lib/
            index.ts
          billing/
            ...
        shared/
          components/
          hooks/
          lib/
    admin/
      app/
        ...                     # Same layer structure
      src/
        features/
          ...
  packages/
    ui/                         # Shared primitives
    auth/                       # Shared auth logic
    database/                   # Prisma + queries
    config/                     # ESLint, TS, Tailwind configs
    utils/                      # Generic helpers
  turbo.json
  package.json
</code></pre>
<p>Notice how the <code>'use client'</code> boundary appears only at the interactive leaves: <code>ChartSection.tsx</code> needs <code>useState</code>, and <code>CancelButton.tsx</code> needs a click handler and <code>useTransition</code>. Everything above them (<code>MetricsDashboard.tsx</code>, <code>OrderTimeline.tsx</code>, the page components) stays on the server, fetching data and composing layout without shipping any JavaScript to the browser.</p>
<p>The layers stack cleanly:</p>
<ol>
<li><p><strong>Turborepo packages</strong>: the lowest layer. Generic, reusable, no app-specific knowledge.</p>
</li>
<li><p><strong>Shared feature layer</strong>: cross-cutting app concerns. Can consume packages, knows nothing of routes.</p>
</li>
<li><p><strong>Feature modules</strong>: domain logic, encapsulated behind barrel exports.</p>
</li>
<li><p><strong>App Router</strong>: routes, layouts, colocation. Consumes features and packages. Data flows through Server Components, interactivity is delegated to Client Component leaves.</p>
</li>
</ol>
<h2 id="heading-common-pitfalls-and-how-to-avoid-them">Common Pitfalls and How to Avoid Them</h2>
<p><strong>"I'll just put it in</strong> <code>/utils</code> <strong>for now."</strong> This is how junk drawers form. If you can't name what a utility belongs to, it probably needs a new feature folder, not a generic dumping ground.</p>
<p><strong>Over-extracting packages too early</strong>: Not everything needs to be a shared package. Start in the app, extract to a package only when a second consumer appears. The cost of premature abstraction is maintenance overhead and false coupling.</p>
<p><strong>Client Components at the top of every tree</strong>: If your route's <code>page.tsx</code> has <code>'use client'</code> at the top, you've lost most of what Server Components give you. Push the directive down to the interactive leaf.</p>
<p><strong>Circular package dependencies</strong>: If <code>packages/auth</code> imports from <code>packages/database</code> and <code>packages/database</code> imports from <code>packages/auth</code>, you have a cycle. Keep the dependency graph a DAG: each package should have one clear level of abstraction.</p>
<p><strong>Barrel files that export everything</strong>: The barrel file is a public API, not an index of every file in the folder. Export only what other parts of the app are meant to use.</p>
<h2 id="heading-final-thoughts">Final Thoughts</h2>
<p>Good architecture isn't about finding the perfect structure, it's about making the right decisions easy and the wrong decisions hard.</p>
<ul>
<li><p><strong>Colocation</strong> makes it easy to find what you need.</p>
</li>
<li><p><strong>Feature modules</strong> make it hard to accidentally couple unrelated domains.</p>
</li>
<li><p><strong>Turborepo</strong> makes it easy to share code and hard to duplicate it.</p>
</li>
<li><p><strong>Server Components</strong> make it easy to fetch data where you need it and hard to send unnecessary JavaScript to the browser.</p>
</li>
</ul>
<p>None of these ideas are new. Layered architecture, separation of concerns, and encapsulation are decades-old principles. What Next.js and Turborepo give you is a modern toolkit to express them idiomatically in a JavaScript codebase.</p>
<p>The best time to set this up is at the start of a project. The second best time is now, before the next feature makes untangling things twice as hard.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How Microfrontends Work: From iframes to Module Federation ]]>
                </title>
                <description>
                    <![CDATA[ Microfrontends are transforming how teams build and deploy frontend applications at scale. This tutorial explores the architectural landscape, from traditional approaches to modern Module Federation implementations. By the end, you'll be equipped to ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-microfrontends-work-iframes-to-module-federation/</link>
                <guid isPermaLink="false">6839c4a906e067fe415d54b4</guid>
                
                    <category>
                        <![CDATA[ frontend ]]>
                    </category>
                
                    <category>
                        <![CDATA[ architecture ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Microfrontend ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Frontend Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Rahul gupta ]]>
                </dc:creator>
                <pubDate>Fri, 30 May 2025 14:46:01 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1748613557891/39037981-d514-4f26-8a48-be0cdd9ca29b.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Microfrontends are transforming how teams build and deploy frontend applications at scale. This tutorial explores the architectural landscape, from traditional approaches to modern Module Federation implementations.</p>
<p>By the end, you'll be equipped to evaluate whether microfrontends are the right solution for your team's specific needs.</p>
<h3 id="heading-ill-cover-the-following"><strong>I’ll cover the following:</strong></h3>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-are-microfrontends">What are Microfrontends?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-traditional-microfrontend-patterns">Traditional Microfrontend Patterns</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-server-side-composition">Server-Side Composition</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-iframes">iframes</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-build-time-integration-packages">Build Time Integration – Packages</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-modern-microfrontend-patterns">Modern Microfrontend Patterns</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-module-federation">Module Federation</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-single-spa">Single SPA</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-detailed-comparison">Detailed Comparison</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-tradeoffs-and-challenges-with-module-federation">Tradeoffs and Challenges with Module Federation</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-setup-complexity">Setup Complexity</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-runtime-challenges">Runtime Challenges</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-operational-concerns">Operational Concerns</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusions">Conclusions</a></p>
<ul>
<li><a class="post-section-overview" href="#heading-whats-next">What’s next?</a></li>
</ul>
</li>
</ul>
<h2 id="heading-what-are-microfrontends">What are Microfrontends?</h2>
<p>If you've heard about microservices on the backend, microfrontends represent a similar approach in the frontend world, with many of the same benefits.</p>
<p>Your team might adopt a microfrontend approach to enable team autonomy, reduce deployment risks, and scale development across multiple teams. Each team owns its technology stack, deployment cadence, and workflows. Yet they still deliver a single, cohesive user interface.</p>
<p>The overall idea is to move away from a big monolithic UI to decoupled UI codebases that can be owned, managed, and deployed by separate teams independently.</p>
<p>The simplest way to think about Microfrontends is the following:</p>
<blockquote>
<p>Integrate one piece of UI into another</p>
</blockquote>
<p>What can this <strong>piece</strong> of UI be, you may ask? Here are some examples:</p>
<ul>
<li><p><strong>Pages</strong> – parts of a website owned by specific teams. For example, the Auth team may own login/signup pages, whereas the engagement team may own the marketing pages, and so on.</p>
</li>
<li><p><strong>Components</strong> – Components like header and footer are good candidates for a microfrontend approach as well. They’re relatively static but need to stay consistent across the website and may integrate with teams who own different sets of pages.</p>
</li>
<li><p><strong>Widgets</strong> – A recommendation widget may be owned by a recommendations team, for example, and it can be integrated into different parts of the page based on the context. This is different from a static component, as given the context, the recommendation widget may also fetch relevant data via APIs (also owned by the recommendations teams).</p>
</li>
</ul>
<h2 id="heading-traditional-microfrontend-patterns">Traditional Microfrontend Patterns</h2>
<p>After reading the definition of a microfrontend, you might be thinking, oh, wait, who builds UI with a big monolith these days anyway (except giants like Google)? If that’s the case, your team is most likely using one of these traditional approaches to building Microfrontends:</p>
<h3 id="heading-server-side-composition"><strong>Server-Side Composition</strong></h3>
<p>This is the most common approach I've encountered across various organisations. The idea is to split your website based on route patterns or pages. For example, you might route users to the accounts team for any routes starting with <code>/account/*</code> (<code>/account/login</code> or <code>/account/signup</code> may fall under this pattern). Or you may have a similar route prefix for other parts of your web app, like <code>/blog/*</code> for the marketing section of your app.</p>
<p>This is typically implemented at the reverse proxy layer (such as using NGINX), which routes traffic to the appropriate downstream UI service based on the path matching.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1747496226912/fda979cd-c95c-4d48-a7dc-87956672b24d.png" alt="Diagram showing a reverse proxy setup with nginx. The proxy routes `/blog/*` requests to the Marketing UI and `/account/*` requests to the Accounts UI." class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h3 id="heading-iframes"><strong>iframes</strong></h3>
<p>Another common approach is using iframes, though this method has significant limitations.</p>
<p>Unlike server-side composition, which operates at the page level, iframes can integrate as widgets within pages. Using iframes, you can load another website as a part of the website you want to integrate it within using the <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/iframe">&lt;iframe&gt;</a> tag.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1747496936962/7c24a43a-80d4-45f4-a2df-3de0e0e0bc1c.png" alt="Diagram illustrating iframe integration, showing website.com/blog embedding a 'Widget' using an iframe with source 'website.com/widget'." class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Some examples of this approach, which you may have seen, are websites that integrate Twitter feeds, Google Maps, and so on. Although these are examples of external widget integrations with iframes, companies may integrate certain widgets that are powered through iframes.</p>
<h3 id="heading-build-time-integration-packages"><strong>Build Time Integration – Packages</strong></h3>
<p>This approach involves publishing components as a UI library that other applications can integrate.</p>
<p>This is useful if you want to integrate full-blown apps with multiple pages, widgets, or static components like headers and footers, where this approach is pretty common.</p>
<p>Typically, this approach means that one team publishes their components as a package, while other teams integrate a specific version of this package.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1747497485861/70385841-28c6-441e-ae4d-c977b3563ecf.png" alt="Diagram illustrating build-time integration via packages, showing website.com/blog integrating a 'Widget' component, version 1.0.0, fetched from a company's NPM registry." class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>In this example, it’s important to note that the Widget component is pulled in during the dependency install phase of the app. The web app can utilise this widget like its own component, which gets built together as one module and shipped to the users.</p>
<h2 id="heading-modern-microfrontend-patterns">Modern Microfrontend Patterns</h2>
<h3 id="heading-module-federation">Module Federation</h3>
<p>Module Federation enables you to integrate remote UI pieces within a host application at runtime. These pieces can be full pages, widgets, or components.</p>
<p>Module Federation originated as a <a target="_blank" href="https://webpack.js.org/concepts/module-federation/">Webpack 5 feature</a>, extending the bundler's capabilities to load JavaScript code from remote sources at runtime.</p>
<p><a target="_blank" href="https://module-federation.io/">Module Federation 2.0</a> is the evolution/improvement of the original Webpack 5 feature, with implementations available for other popular bundlers like RSPack and Vite as well.</p>
<p>Even if you’re using Webpack 5, I would recommend using Module Federation 2.0 as it takes care of some common gotchas that exist in the original Webpack 5 implementation.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748011963774/fae404c6-efc9-4e0f-8667-4427dbcdfc0f.png" alt="Diagram illustrating Module Federation, showing a host application at website.com/blog loading a 'Widget' component at runtime from a remote application at Recommendation.com via 'remotes: recommendation/remoteEntry'." class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Let’s take an example to understand some of the common pieces of Module Federation.</p>
<p>Imagine that we’ve a blog application, owned by the Content Team &amp; a Widget, which is owned by the Recommendations team.</p>
<p>Now, let’s say the content team wants to integrate a recommendation widget within their application. Assume these teams have separate codebases hosted on different domains. The content team is on <code>website.com</code> &amp; the recommendations team is on <code>recommendation.com</code></p>
<p>Here’s how you can achieve this MFE integration via Module Federation:</p>
<h4 id="heading-remote"><strong>Remote</strong></h4>
<p>Responsible for exposing JavaScript files as remote (for example, utilities, components, and so on).</p>
<p>In our example, it would be the Recommendation’s team acting as a remote &amp; would require a configuration to ‘expose’ the Widget.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">new</span> ModuleFederationPlugin({
  name: <span class="hljs-string">'recommendation'</span>,
  exposes: {
    <span class="hljs-string">'./Widget'</span>: <span class="hljs-string">'./src/Widget.js'</span>,
  }
})
</code></pre>
<h4 id="heading-remote-entry"><strong>Remote Entry</strong></h4>
<p>Remote entry is the URL for the entry point for a remote. A remote may expose multiple JavaScript files, &amp; remoteEntry file would be aware of all of them.</p>
<p>Module Federation by default hosts the remote entry file at the root. In our example, recommendation teams might host their remote entry on <code>https://recommendation.com/remoteEntry.js</code></p>
<h4 id="heading-host"><strong>Host</strong></h4>
<p>An independent website that consumes JavaScript from one or more remotes via <strong>Remote Entry.</strong> Think of remote entry as a namespace for your app under which it can export multiple things like components, utils, and so on, as exposed by a particular remote.</p>
<p>In our example, the Content Team would act as a Host &amp; they’ll define the recommendation team’s remote entry within remotes configuration.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">new</span> ModuleFederationPlugin({
  name: <span class="hljs-string">'content-blog'</span>,
  remotes: {
    <span class="hljs-string">"recommendation"</span>: <span class="hljs-string">'recommendation@https://recommendation.com/remoteEntry.js'</span>,
  },
  <span class="hljs-comment">// ... other configs</span>
})
</code></pre>
<h4 id="heading-shared"><strong>Shared</strong></h4>
<p>Both hosts and remote can specify dependencies as SemVer that are automatically negotiated and shared during runtime. These can include common framework dependencies, such as React, which may require being a singleton, or other vendor libraries that can be potentially shared.</p>
<p>Having the right shared configuration ensures that the client does not download libraries or code that is already available on the host when fetching UI pieces from a remote location, which is key for optimal performance when integrating Module Federation.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> deps = <span class="hljs-built_in">require</span>(<span class="hljs-string">"./package.json"</span>).dependencies;

<span class="hljs-keyword">new</span> ModuleFederationPlugin({
  shared: {
    ...deps,
    react: {
      singleton: <span class="hljs-literal">true</span>,
      requiredVersion: deps.react,
    }
  },
  <span class="hljs-comment">// ... other configs</span>
})
</code></pre>
<h4 id="heading-imports-and-usage"><strong>Imports and Usage</strong></h4>
<p>Module Federation integration lets you use imports as if those JS files were available locally. Module Federation does all the stitching behind the scenes at runtime, in terms of fetching the remote entry and appropriate dependencies to make it available when you use it.</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// Import is of the format - &lt;remote&gt;/&lt;expose-from-remote&gt;</span>
<span class="hljs-keyword">import</span> Widget <span class="hljs-keyword">from</span> <span class="hljs-string">'recommendation/Widget'</span>;

<span class="hljs-comment">// Render somewhere, making sure to handle loading via Suspense</span>
<span class="hljs-comment">// &amp; errors via error boundary in React</span>
&lt;ErrorBoundary&gt;
  &lt;Suspense fallback={&lt;Loading /&gt;}
    &lt;Widget /&gt;
  &lt;/Suspense&gt;
&lt;/ErrorBoundary&gt;
</code></pre>
<p>In a nutshell, the module federation concept is this simple —</p>
<blockquote>
<p>Fetching JS code (components, utils, and so on) from a remote server at runtime and still being able to share dependencies and be performant while doing so.</p>
</blockquote>
<h3 id="heading-single-spa">Single SPA</h3>
<p>When you look up microfrontends, <a target="_blank" href="https://single-spa.js.org">Single SPA</a> often appears as a popular solution. But its primary use case is quite specific: integrating components across multiple frameworks (for example, React + Angular + Vue in the same application). Here's how it works in practice:</p>
<p>Single SPA acts as a JavaScript router that mounts and unmounts entire applications based on URL routes. Each "single-spa application" is a framework-specific app that gets loaded when its route becomes active.</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// Register applications with Single SPA</span>
registerApplication({
 name: <span class="hljs-string">'@mycompany/react-app'</span>,
 app: <span class="hljs-function">() =&gt;</span> System.import(<span class="hljs-string">'@mycompany/react-app'</span>),
 activeWhen: [<span class="hljs-string">'/react-app'</span>]
});

registerApplication({
 name: <span class="hljs-string">'@mycompany/angular-app'</span>, 
 app: <span class="hljs-function">() =&gt;</span> System.import(<span class="hljs-string">'@mycompany/angular-app'</span>),
 activeWhen: [<span class="hljs-string">'/angular-app'</span>]
});
</code></pre>
<p>Single SPA handles the "orchestration" part – deciding which app should be active and managing their lifecycles. It doesn't solve the "how do I load remote code" problem – you still need to pair it with one of the approaches we've discussed (Module Federation, build-time packages, and so on).</p>
<p>If your applications use the same framework (like all React), you can skip Single SPA entirely and use Module Federation directly. Single SPA adds complexity that's only justified when you truly need multi-framework integration.</p>
<h2 id="heading-detailed-comparison">Detailed Comparison</h2>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Criteria</strong></td><td><strong>Module Federation</strong></td><td><strong>Server-side composition</strong></td><td><strong>iframe</strong></td><td><strong>Build time integration (package)</strong></td></tr>
</thead>
<tbody>
<tr>
<td><strong>Independent deployments</strong></td><td>💚 Microfrontends are loaded at runtime on the client. This means that teams can do independent deployments and make changes that reflect immediately.</td><td>💚 Deployments stay independent, as each route pattern points to an individual app’s independent deployments</td><td>💚 Since iframes are also loaded at runtime, the deployments can be independent.</td><td>💔 Deployments are coupled from the host application. A change in the package would require publishing a new version and bumping it up in the host app.</td></tr>
<tr>
<td><strong>Performance</strong></td><td>💚 Enables shared dependencies and optimised loading, maintaining SPA performance.</td><td>💔 Requires full page reloads when navigating between applications, losing SPA benefits.</td><td>💔 Completely isolated and loads all the dependencies of the website in an iframe, which means a slower overall page load.</td><td>💚 Possible to share package dependencies to a certain extent by <a target="_blank" href="https://yarnpkg.com/cli/dedupe">deduping</a> dependencies when integrating a package, but it requires appropriate dev tooling. Otherwise, duplicate dependencies may sneak in for the same package.</td></tr>
<tr>
<td><strong>Scalability &amp; maintenance</strong></td><td>💚 Works well at scale. A page can be completely composed of federated components, with the smallest of the building blocks being pulled in from different remotes.</td><td>💔 Usually requires duplicating things like header/footer, to make it ‘look like’ the user is in the same app, but is being served by two different servers/codebases. The approach is limited to route-based segregation of apps’ entry points – so, a granular integration isn’t possible.</td><td>💔 Typically good to power whole pages and not portions of pages, can really slow down the app at scale and may encounter issues when optimising the app for SEO or building dynamic responsive layouts.</td><td>💔 Requires maintenance of package publishing, upgrades and version conflicts at scale. This can be simplified to some extent by CI tooling, but developers would still require significant effort in bumping the versions, verifying the impact from a feature/performance standpoint.</td></tr>
<tr>
<td><strong>Setup effort</strong></td><td>💔 Might be high depending on how your app is being built currently. A deeper level of understanding of your build tool may be required to make your desired integration work, or when you face issues. This is covered in detail in the next section.</td><td>💚 Simpler to implement, as there is no coupling apart from the reverse proxy layer, which is responsible for redirecting the traffic to the appropriate service.</td><td>💔 Easier to integrate but requires handling a lot of edge cases, which can take significant time. Some examples are communication between iframe/host app, layout issues, rendering beyond the boundaries of iframe (for example, toasts), cross-domain iframe restrictions and ensuring security, impact on SEO and a11y.</td><td>💔 Requires significant effort to stabilise the development pipeline for publishing a new package, maintaining a changeset, bumping a new version, and resolving version conflicts. Every change requires making sure there is no unintended impact on transitive dependencies of the host app due to the package bump.</td></tr>
<tr>
<td><strong>Authentication &amp; Authorisation</strong></td><td>💚 Depending on your app’s setup, module federated components can call the remote app’s server for any data fetching needs. Might require handling CORS if your remote is on a different domain than the host, and for the browser to send authentication cookies for such requests.</td><td>💚 Each app can independently integrate with a central authentication service.</td><td>💔 It can be challenging for iframes to access the parent website’s browser details like auth cookies, and so on. It also may require some trickery to get the authentication to work, especially if the iframe URL is on a different domain/subdomain than the application.</td><td>💚 Package components can choose to call APIs via a proxy API within the host application or directly integrate with an independent service’s endpoints.</td></tr>
<tr>
<td><strong>Devloop</strong></td><td>💚 Mature devloop with Module Federation 2.0, you can view source maps with hot reloading across these apps. Overall a seamless integration out of the box. You can also point to any federated endpoint from local to be able to integrate and verify end-to-end integration.</td><td>💔 Requires setting up both services and a reverse proxy locally to verify integration touchpoints, which may be non-trivial.</td><td>💔 Local testing doesn’t accurately mimic the issues that you may face due to cross-domain challenges with iframe.</td><td>💔 An appropriate dev workflow is required to test the in-development package changes within the host app locally. This is typically done with pre-publishing the package or by <a target="_blank" href="https://classic.yarnpkg.com/lang/en/docs/cli/link/">linking</a> local packages or using a tool like <a target="_blank" href="https://github.com/wclr/yalc">yalc</a>.</td></tr>
<tr>
<td><strong>Overall Recommendation ✨</strong></td><td>Suited for apps that are composed of integration with different teams who want to own their deployments and release cycles with low coupling.</td><td>Suited for apps that are rather isolated (subdomains) within a larger business domain. A question to ask is, how often would the user need to navigate between these apps? If the answer is ‘not often’, then this may be a suitable approach.</td><td>Not recommended due to the limitations that come with it. It may be suitable for some third-party integrations, for example, Twitter exposes a part of its feed which can be integrated within a website via iframe. This is rather more convenient than any of the other approaches.</td><td>Suited for apps where the changes need to be more controlled, with the host app upgrading the package, and may perform appropriate checks before releasing it to their end users.</td></tr>
</tbody>
</table>
</div><h2 id="heading-tradeoffs-and-challenges-with-module-federation">Tradeoffs and Challenges with Module Federation</h2>
<p>The primary tradeoff in using Module Federation is the initial setup effort, which I briefly discussed in the previous comparison table.</p>
<p>Here are some other challenges to anticipate when integrating via Module Federation:</p>
<h3 id="heading-setup-complexity"><strong>Setup Complexity</strong></h3>
<ol>
<li><p><strong>Bundler-specific challenges</strong> – Some things may require you to know your bundler's internals to make the integration work for your app. For example, with Webpack 5, if your remote not only exposes federated components but also serves a user experience, you’ll need the appropriate chunk setup to make that work. This is because Module Federation by default expects a certain chunk optimisation strategy and exposes the remoteEntry from the root of the app.</p>
</li>
<li><p><strong>Shared dependencies</strong> – You'll need to review your dependencies to make sure you share as many dependencies as possible to optimise bundle size and loading performance. You’ll also need to mark critical libraries (like React) as singletons to prevent runtime conflicts.</p>
</li>
</ol>
<h3 id="heading-runtime-challenges"><strong>Runtime Challenges</strong></h3>
<ol>
<li><p><strong>Cross domain</strong> – if your remote is on a different subdomain, for example <code>remote.website.com</code> and is being loaded from <code>host.website.com</code> You’ll need appropriate handling for CORS on your server to allow data fetching from the host’s subdomain. You’ll also need an appropriate <code>credentials</code> fetch configuration to make sure the browser sends the authentication cookies in data fetching requests to your remote endpoints.</p>
</li>
<li><p><strong>Styling conflicts</strong> – You’ll want to make sure the remote’s styles don’t override the host’s styles and that the remote components don’t inherit unintended styles from the host. There are multiple strategies here, from using styled components to a virtual DOM.</p>
</li>
</ol>
<h3 id="heading-operational-concerns"><strong>Operational Concerns</strong></h3>
<ol>
<li><p><strong>Observability and Analytics</strong> – Based on your requirements, you may want to either share an instance of your observability scripts, for example, an error monitoring service, or instantiate a completely different one within your MFE’s context. This becomes challenging, as there is no ‘index’ file being rendered, but rather components that are being exposed from the remotes.</p>
</li>
<li><p><strong>Deployment &amp; Caching</strong> – It’s recommended that MFE remote bundles be hosted on S3 buckets for high reliability as opposed to loading them from a remote server. You may require appropriate long-term caching for files other than the <code>remoteEntry.js</code> which is typically non-hashed and contains the link to other dependencies to be loaded.</p>
</li>
</ol>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Microfrontends offer a compelling solution for scaling frontend development across multiple teams, with Module Federation emerging as the most flexible modern approach.</p>
<p>While traditional methods like server-side composition remain valuable for specific use cases, Module Federation provides the runtime flexibility and performance characteristics needed for complex applications.</p>
<p>The decision ultimately depends on your team’s structure, technical requirements, and tolerance for implementation complexity. Start with simpler approaches if you're new to microfrontends, then consider Module Federation as your needs evolve.</p>
<h3 id="heading-whats-next">What’s next?</h3>
<p>This article was more about giving you a bird’s-eye view of the landscape. I’ll be writing more on Module Federation and going beyond the basics next. I’ll cover the technical challenges in more detail, along with possible solutions. Watch out for the same!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Learn API Fundamentals and Architecture – A Beginner-Friendly Guide ]]>
                </title>
                <description>
                    <![CDATA[ Here are some questions for you: How do you log in to apps with your Google, Apple, or Microsoft account? How do online payments with Paystack or PayPal work? How do apps like Facebook and Instagram share information and notifications? The answer is:... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/learn-api-fundamentals-and-architecture/</link>
                <guid isPermaLink="false">67dd93c136028f6326576025</guid>
                
                    <category>
                        <![CDATA[ APIs ]]>
                    </category>
                
                    <category>
                        <![CDATA[ architecture ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ikegah Oliver ]]>
                </dc:creator>
                <pubDate>Fri, 21 Mar 2025 16:28:49 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1742310491936/3e9eb6e8-9f7d-424a-821e-b7110e3cf2f0.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Here are some questions for you: How do you log in to apps with your Google, Apple, or Microsoft account? How do online payments with Paystack or PayPal work? How do apps like Facebook and Instagram share information and notifications?</p>
<p>The answer is: they use APIs. These are powerful tools that drive mobile and web development and a wide range of applications, including cloud services, IoT devices, desktop software, and more.</p>
<p>APIs enable communication between applications, facilitating data exchange and verification.</p>
<p>In this article, you’ll learn all about APIs: the different types, their architecture, and the tradeoffs between the different architectures.</p>
<h3 id="heading-heres-what-well-cover">Here’s what we’ll cover:</h3>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-is-an-api">What is an API?</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-how-do-apis-work">How Do APIs Work?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-why-are-apis-important">Why Are APIs Important?</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-types-of-apis">Types of APIs</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-open-apis">Open APIs</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-partner-apis">Partner APIs</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-internal-apis">Internal APIs</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-composite-apis">Composite APIs</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-types-of-api-architecture">Types of API Architecture</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-rest-apis">REST APIs</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-soap-apis">SOAP APIs</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-graphql-apis">GraphQL APIs</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-grpc-apis">gRPC APIs</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-choose-an-api-architecture">How to Choose an API Architecture</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion-and-future-trends">Conclusion and Future Trends</a></p>
</li>
</ul>
<p>This article is well-suited for beginners in web and mobile development and developers seeking a concise understanding of APIs and how they function.</p>
<h2 id="heading-what-is-an-api">What is an API?</h2>
<p>API stands for Application Programming Interface. It is a set of rules and protocols that lets different software systems communicate with each other. An API defines how applications request services and exchange data, acting as a clear contract between a client and a server.</p>
<p>APIs simplify complex code into simple commands, letting developers connect systems and use built-in features without needing to know all the internal workings.</p>
<h3 id="heading-how-do-apis-work">How Do APIs Work?</h3>
<p>Imagine a restaurant: the customer (client) orders food through the waiter (API), who then communicates the order to the kitchen (server). The kitchen prepares the meal and sends it back through the waiter to the customer. Just like the waiter, the API handles requests and responses, letting the customer enjoy the meal without needing to know the details of the kitchen's operations.</p>
<p>A more practical example is when you buy a subscription online, and your payment information is securely sent to Paystack through its payment API. The API is a middleman that takes your request, verifies and processes your payment details with the bank, and then returns a confirmation to the website without directly exposing sensitive data.</p>
<p>Technically, a client initiates a request aimed at a server, specifying either data retrieval or procedural execution. Upon receiving and authenticating this request, the API performs the required operations. Then the API sends a response to the client, including the request's outcome (success or failure) and any requested data elements.</p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXeho5OxXyKdS_-Sam70CtbZIH6y1wFMH3r21I0ZeNDVFNqoY0Jr2Lk5u_FfsiIas6LEnMPjRbQticIaDZi0iCF93Zj-JpxjZzXrwEGtdS_vIopXEUtNG5mvVHnVpf5vvhZGHw4Q?key=2qCWq-hs7d172uM7WbtEHg_B" alt="Diagram from shiksha.com illustrating how an API works." width="600" height="400" loading="lazy"></p>
<h3 id="heading-why-are-apis-important">Why Are APIs Important?</h3>
<p>APIs are crucial in software development because they make connecting different applications and services easier. They let you integrate external functionalities without building everything from scratch, saving time and reducing complexity through standardised commands.</p>
<p>For users, APIs also enhance security and user experience. They serve as secure gateways that filter data exchange between apps and external services, protecting sensitive information while ensuring smooth, reliable interactions.</p>
<h2 id="heading-types-of-apis">Types of APIs</h2>
<p>API types are mainly categorised by their accessibility and usage. There are four types of APIs, namely:</p>
<ol>
<li><p>Open (Public) APIs</p>
</li>
<li><p>Partner APIs</p>
</li>
<li><p>Internal (Private) APIs</p>
</li>
<li><p>Composite APIs</p>
</li>
</ol>
<h3 id="heading-open-apis">Open APIs</h3>
<p>Open APIs are APIs made available to the general public. This encourages developers, organisations, and other people to use them to develop applications, integrate them into their services, and improve them. Open APIs provide standardised access to data or services over the Internet.</p>
<p>Some very useful Open APIs include:</p>
<ul>
<li><p><a target="_blank" href="https://tradewatch.io/">TradeWatch</a> – Real-time financial market data</p>
</li>
<li><p><a target="_blank" href="http://serpapi.com">SerpAPI’s Search API</a> – Real-time Google SERP API</p>
</li>
<li><p><a target="_blank" href="http://twitterapi.io">TwitterApi.io</a> – Access real-time and historical data</p>
</li>
<li><p><a target="_blank" href="https://instagram-posts-generator.vercel.app/">Instagram Post Generator</a> – Generate posts with templates from popular IG pages</p>
</li>
</ul>
<h3 id="heading-partner-apis">Partner APIs</h3>
<p>Partner APIs are shared with specific business partners and often require authentication and agreements. They perform essential functions for businesses and applications.</p>
<p>For example, a payment API like Paystack directly communicates with service providers and banking platforms to process payments for products and services.</p>
<h3 id="heading-internal-apis">Internal APIs</h3>
<p>Internal APIs are used for internal communication within an organisation. They enable integration and streamline internal processes. Internal teams use the API to access and share data between their applications. The API is not exposed to the public, ensuring that sensitive business logic remains secure.</p>
<p>An example is a company’s internal API that connects its HR, payroll, and project management systems.</p>
<h3 id="heading-composite-apis">Composite APIs</h3>
<p>Composite APIs combine multiple API calls into a single request. They are instrumental in microservices architectures, where a single operation may require data from several services. A single API call triggers requests to multiple underlying APIs, and the composite API then combines the responses and returns a unified result.</p>
<p>For example, an e-commerce platform might use a composite API to fetch product details, pricing, and inventory information in one go, reducing latency and simplifying the integration process.</p>
<h2 id="heading-types-of-api-architecture">Types of API Architecture</h2>
<p>APIs are structured differently depending on use case, scalability, security, and accessibility. There are multiple ways to structure an API, but we will only focus on the most prevalent architectural styles used in Web development. They include:</p>
<ol>
<li><p>REST</p>
</li>
<li><p>SOAP</p>
</li>
<li><p>GraphQL</p>
</li>
<li><p>gRPC</p>
</li>
</ol>
<h3 id="heading-rest-apis">REST APIs</h3>
<p>Representational State Transfer (REST) is an architectural style that uses HTTP methods (POST, GET, PUT, DELETE) to perform CRUD (Create, Read, Update, Delete) operations on resource-based URIs.</p>
<p>REST APIs are built with frameworks like Express.js (Node.js), Django/Flask (Python), and Spring Boot (Java).</p>
<h4 id="heading-key-components">Key Components</h4>
<ol>
<li><p>Resources and endpoints:</p>
<ul>
<li><p>The entities exposed by the API can include anything: users, products, documents, and so on.</p>
</li>
<li><p>Each resource is identified by a unique URI (Uniform Resource Identifier).</p>
</li>
</ul>
</li>
<li><p>HTTP methods:</p>
<ul>
<li><p>GET: Retrieves a resource.</p>
</li>
<li><p>POST: Creates a new resource.</p>
</li>
<li><p>PUT: Updates an existing resource.</p>
</li>
<li><p>DELETE: Removes a resource.</p>
</li>
<li><p>PATCH: Partially updates an existing resource.</p>
</li>
</ul>
</li>
<li><p>Data representation:</p>
<ul>
<li><p>Resources can have multiple representations (for example, JSON, XML).</p>
</li>
<li><p>The API responds with the requested representation, allowing data to be structured and parsed easily.</p>
</li>
</ul>
</li>
<li><p>HTTP headers and query parameters:</p>
<ul>
<li><p>HTTP headers provide additional information about the request or response.</p>
</li>
<li><p>They can be used for authentication, content negotiation, and other purposes.</p>
</li>
</ul>
</li>
<li><p>Statelessness:</p>
<ul>
<li><p>Each request from a client to a server must contain all the information needed to understand and process the request.</p>
</li>
<li><p>The server does not store any client state between requests.</p>
</li>
</ul>
</li>
</ol>
<p>Other notable components are cacheability, HTTP Status, and HATEOAS. Together, these components define the structure and behaviour of RESTful systems, enabling seamless and efficient communication between clients and servers.</p>
<h4 id="heading-operation-overview">Operation Overview</h4>
<p>REST APIs expose resources through unique URIs and let clients perform operations using HTTP methods such as GET, POST, PUT, DELETE, and PATCH. Clients can request data in various formats, such as JSON or XML, and include additional details through HTTP headers and query parameters.</p>
<p>Each request is stateless and contains all the information required for processing without relying on stored client data. The API also uses HTTP status codes, cacheability, and HATEOAS to manage responses and guide further interactions, ensuring a seamless and efficient communication framework between clients and servers.</p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXcYW8ovzOrZJB1eV1X82hvfuddZwjl7mwI56bYpZKCvzf4I4tNEfx58lhIjs_GMRaei9mXAxR78BUAIacBYoCw4J-CmkVKRDGa5ruK4KdYnmBV2Y0u9qz9QjOYSWNHBmUIPsopXuA?key=2qCWq-hs7d172uM7WbtEHg_B" alt="Diagram from apisec.ai illustrating the flow of a REST API, including endpoints, HTTP methods, and data exchange between client and server." width="600" height="400" loading="lazy"></p>
<h4 id="heading-practical-example-and-real-world-use-cases">Practical Example and Real-world Use Cases</h4>
<p>To illustrate how REST APIs work in practice, let’s consider a Book API that lets users manage a collection of books. Our example API has been created using the <a target="_blank" href="https://www.freecodecamp.org/news/get-started-with-nodejs/">NodeJS</a> and <a target="_blank" href="https://expressjs.com/">ExpressJS</a> frameworks. I won’t explain how these frameworks actually work here, as that’s beyond the scope of this article. So if you don’t understand the syntax in the code below, don’t worry – just focus on the <strong>Requests</strong> and <strong>Responses</strong> logic.</p>
<p>This API follows REST principles by using standard HTTP methods to perform CRUD (Create, Read, Update, Delete) operations:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">"express"</span>); <span class="hljs-keyword">const</span> bodyParser = <span class="hljs-built_in">require</span>(<span class="hljs-string">"body-parser"</span>);
<span class="hljs-keyword">const</span> app = express(); app.use(bodyParser.json());

<span class="hljs-keyword">const</span> app = express();
app.use(bodyParser.json());

<span class="hljs-comment">// Dummy Database</span>
<span class="hljs-keyword">let</span> books = [
  { <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">title</span>: <span class="hljs-string">"The Pragmatic Programmer"</span>, <span class="hljs-attr">author</span>: <span class="hljs-string">"Andy Hunt"</span> },
  { <span class="hljs-attr">id</span>: <span class="hljs-number">2</span>, <span class="hljs-attr">title</span>: <span class="hljs-string">"Clean Code"</span>, <span class="hljs-attr">author</span>: <span class="hljs-string">"Robert C. Martin"</span> },
];

<span class="hljs-comment">// GET all books (Client requests, Server responds)</span>
app.get(<span class="hljs-string">"/books"</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> res.json(books));

<span class="hljs-comment">// GET a single book by ID</span>
app.get(<span class="hljs-string">"/books/:id"</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> book = books.find(<span class="hljs-function">(<span class="hljs-params">b</span>) =&gt;</span> b.id === <span class="hljs-built_in">parseInt</span>(req.params.id));
  book ? res.json(book) : res.status(<span class="hljs-number">404</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">"Not found"</span> });
});

<span class="hljs-comment">// POST a new book (Client sends data, Server updates database)</span>
app.post(<span class="hljs-string">"/books"</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> newBook = { <span class="hljs-attr">id</span>: books.length + <span class="hljs-number">1</span>, ...req.body };
  books.push(newBook);
  res.status(<span class="hljs-number">201</span>).json(newBook);
});

<span class="hljs-comment">// PUT (Update) a book</span>
app.put(<span class="hljs-string">"/books/:id"</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> book = books.find(<span class="hljs-function">(<span class="hljs-params">b</span>) =&gt;</span> b.id === <span class="hljs-built_in">parseInt</span>(req.params.id));
  <span class="hljs-keyword">if</span> (book) {
    <span class="hljs-built_in">Object</span>.assign(book, req.body);
    res.json(book);
  } <span class="hljs-keyword">else</span> {
    res.status(<span class="hljs-number">404</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">"Not found"</span> });
  }
});

<span class="hljs-comment">// DELETE a book</span>
app.delete(<span class="hljs-string">"/books/:id"</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> index = books.findIndex(<span class="hljs-function">(<span class="hljs-params">b</span>) =&gt;</span> b.id === <span class="hljs-built_in">parseInt</span>(req.params.id));
  <span class="hljs-keyword">if</span> (index !== <span class="hljs-number">-1</span>) {
    books.splice(index, <span class="hljs-number">1</span>);
    res.json({ <span class="hljs-attr">message</span>: <span class="hljs-string">"Deleted"</span> });
  } <span class="hljs-keyword">else</span> {
    res.status(<span class="hljs-number">404</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">"Not found"</span> });
  }
});

app.listen(<span class="hljs-number">3000</span>, <span class="hljs-function">() =&gt;</span> <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"API running on port 3000"</span>));
</code></pre>
<p>Here’s what’s going on in this code:</p>
<ul>
<li><p>Client sends a request: A user (or frontend app) requests data using HTTP methods like GET, POST, PUT, or DELETE. Example: GET <code>/books</code> requests all books or POST <code>/books</code> posts a new book to the database.</p>
</li>
<li><p>Server processes the request: The server receives the request, looks up the data (for example, from a database or in-memory array), and processes it.</p>
</li>
<li><p>Server sends a response: The server sends back a JSON response containing the requested data or a confirmation message. Here’s an example:</p>
</li>
</ul>
<pre><code class="lang-json">[
  { <span class="hljs-attr">"id"</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">"title"</span>: <span class="hljs-string">"The Pragmatic Programmer"</span>, <span class="hljs-attr">"author"</span>: <span class="hljs-string">"Andy Hunt"</span> },
  { <span class="hljs-attr">"id"</span>: <span class="hljs-number">2</span>, <span class="hljs-attr">"title"</span>: <span class="hljs-string">"Clean Code"</span>, <span class="hljs-attr">"author"</span>: <span class="hljs-string">"Robert C. Martin"</span> }
]
</code></pre>
<ul>
<li>Client receives and uses the data: The frontend or another service consumes the API response and displays or processes it accordingly.</li>
</ul>
<p>Teams utilize REST APIs for web services, mobile apps, and cloud integrations. Social media platforms fetch posts, while e-commerce sites retrieve product details. Payment gateways process transactions and weather apps access real-time forecasts. REST’s simplicity and scalability make it the preferred choice for public and internal APIs.</p>
<h3 id="heading-soap-apis">SOAP APIs</h3>
<p>The Simple Object Access Protocol (SOAP) uses XML for messaging and includes built-in standards for security, transactions, and error handling. Its formal contract is defined by a WSDL (Web Services Description Language).</p>
<p>This architecture prioritises security and reliability through features like WS-Security and transaction management, making it suitable for complex enterprise applications that require rigid standards and robust error handling.</p>
<p>SOAP APIs are created using frameworks or tools such as Apache CXF, .NET WCF, and JAX-WS (Java).</p>
<h4 id="heading-key-components-1">Key Components</h4>
<ol>
<li><p>SOAP envelope:</p>
<ul>
<li><p>This is the root element of a SOAP message and defines the overall structure of the XML document.</p>
</li>
<li><p>It contains the SOAP Header and SOAP Body.</p>
</li>
</ul>
</li>
<li><p>SOAP body:</p>
<ul>
<li><p>This section contains the actual data being exchanged between the client and server.</p>
</li>
<li><p>It includes the request or response messages, which are typically structured as XML elements.</p>
</li>
</ul>
</li>
<li><p>WSDL (Web Services Description Language):</p>
<ul>
<li><p>This is an XML document that describes the web service, including its operations, message formats, and data types.</p>
</li>
<li><p>It acts as a contract between the client and server, outlining how to interact with the API.</p>
</li>
</ul>
</li>
<li><p>SOAP processor:</p>
<ul>
<li><p>This is the software component that processes SOAP messages.</p>
</li>
<li><p>It parses the XML document, extracts the relevant data, and performs the requested operation.</p>
</li>
</ul>
</li>
</ol>
<p>There is also the SOAP Endpoint, which is the URL where the SOAP service can be accessed, and the XML Schema (XSD), which defines the structure and data types used in the SOAP message's XML.</p>
<h4 id="heading-operation-overview-1">Operation Overview</h4>
<p>SOAP APIs operate by encapsulating data within an XML-based structure defined by a SOAP Envelope, which contains both a Header for metadata and a Body for the actual request or response information. The Body carries the exchange data, while a WSDL document serves as a contract detailing the service's operations, message formats, and data types.</p>
<p>A SOAP Processor then parses the XML, extracts relevant data, and executes the requested operations according to rules defined by an accompanying XML Schema (XSD). Communication with the service occurs through a specific SOAP Endpoint, ensuring a standardised, interoperable framework for web service interactions.</p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXfN_kg7EZxppR62_usgGiNO7jTLWnrmd5MYzxLUyjl6cNSuVHBAVV-kWvQN2xZ5s1acOugK8SfGb2JKtIys01yMSrdRO7iwNCtc5CHh6QDDCBWH2vc7EYOiHNgpbyZv8jZBhTwejg?key=2qCWq-hs7d172uM7WbtEHg_B" alt="Diagram from muledreamin.com illustrating the flow of a SOAP API, including HTTP transfer, and data exchange between SOAP sender and SOAP receive." width="600" height="400" loading="lazy"></p>
<h4 id="heading-practical-examples-and-real-world-use-cases">Practical Examples and Real-world Use Cases</h4>
<p>To illustrate SOAP APIs and how they work practically, let’s consider a SOAP-based Banking Service API that provides secure operations for managing accounts and transactions. SOAP APIs use XML messaging to ensure secure and structured communication between systems. Creating a SOAP API and XML messaging is beyond the scope of this article, so here we’ll just focus on the Request and Response logic.</p>
<p>How it works:</p>
<ul>
<li><strong>Retrieve account information</strong>: The client sends an XML request to fetch a user’s account details:</li>
</ul>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">soapenv:Envelope</span> <span class="hljs-attr">xmlns:soapenv</span>=<span class="hljs-string">"http://schemas.xmlsoap.org/soap/envelope/"</span>
                  <span class="hljs-attr">xmlns:bank</span>=<span class="hljs-string">"http://example.com/bank"</span>&gt;</span>
   <span class="hljs-tag">&lt;<span class="hljs-name">soapenv:Header</span>/&gt;</span>
   <span class="hljs-tag">&lt;<span class="hljs-name">soapenv:Body</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">bank:GetAccountDetails</span>&gt;</span>
         <span class="hljs-tag">&lt;<span class="hljs-name">bank:AccountNumber</span>&gt;</span>123456789<span class="hljs-tag">&lt;/<span class="hljs-name">bank:AccountNumber</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">bank:GetAccountDetails</span>&gt;</span>
   <span class="hljs-tag">&lt;/<span class="hljs-name">soapenv:Body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">soapenv:Envelope</span>&gt;</span>
</code></pre>
<p>The server responds with an XML message containing the account details:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">soapenv:Envelope</span> <span class="hljs-attr">xmlns:soapenv</span>=<span class="hljs-string">"http://schemas.xmlsoap.org/soap/envelope/"</span>&gt;</span>
   <span class="hljs-tag">&lt;<span class="hljs-name">soapenv:Body</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">GetAccountDetailsResponse</span>&gt;</span>
         <span class="hljs-tag">&lt;<span class="hljs-name">AccountNumber</span>&gt;</span>123456789<span class="hljs-tag">&lt;/<span class="hljs-name">AccountNumber</span>&gt;</span>
         <span class="hljs-tag">&lt;<span class="hljs-name">Balance</span>&gt;</span>5000.00<span class="hljs-tag">&lt;/<span class="hljs-name">Balance</span>&gt;</span>
         <span class="hljs-tag">&lt;<span class="hljs-name">Currency</span>&gt;</span>USD<span class="hljs-tag">&lt;/<span class="hljs-name">Currency</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">GetAccountDetailsResponse</span>&gt;</span>
   <span class="hljs-tag">&lt;/<span class="hljs-name">soapenv:Body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">soapenv:Envelope</span>&gt;</span>
</code></pre>
<ul>
<li><p><strong>Process a money transfer</strong>: The client submits a transfer request with authentication details:</p>
<pre><code class="lang-xml">  <span class="hljs-tag">&lt;<span class="hljs-name">soapenv:Envelope</span> <span class="hljs-attr">xmlns:soapenv</span>=<span class="hljs-string">"http://schemas.xmlsoap.org/soap/envelope/"</span>
                    <span class="hljs-attr">xmlns:bank</span>=<span class="hljs-string">"http://example.com/bank"</span>&gt;</span>
     <span class="hljs-tag">&lt;<span class="hljs-name">soapenv:Header</span>/&gt;</span>
     <span class="hljs-tag">&lt;<span class="hljs-name">soapenv:Body</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">bank:TransferFunds</span>&gt;</span>
           <span class="hljs-tag">&lt;<span class="hljs-name">bank:FromAccount</span>&gt;</span>123456789<span class="hljs-tag">&lt;/<span class="hljs-name">bank:FromAccount</span>&gt;</span>
           <span class="hljs-tag">&lt;<span class="hljs-name">bank:ToAccount</span>&gt;</span>987654321<span class="hljs-tag">&lt;/<span class="hljs-name">bank:ToAccount</span>&gt;</span>
           <span class="hljs-tag">&lt;<span class="hljs-name">bank:Amount</span>&gt;</span>100.00<span class="hljs-tag">&lt;/<span class="hljs-name">bank:Amount</span>&gt;</span>
           <span class="hljs-tag">&lt;<span class="hljs-name">bank:Currency</span>&gt;</span>USD<span class="hljs-tag">&lt;/<span class="hljs-name">bank:Currency</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">bank:TransferFunds</span>&gt;</span>
     <span class="hljs-tag">&lt;/<span class="hljs-name">soapenv:Body</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">soapenv:Envelope</span>&gt;</span>
</code></pre>
<p>  If successful, the server returns a confirmation response:</p>
<pre><code class="lang-xml">  <span class="hljs-tag">&lt;<span class="hljs-name">soapenv:Envelope</span> <span class="hljs-attr">xmlns:soapenv</span>=<span class="hljs-string">"http://schemas.xmlsoap.org/soap/envelope/"</span>&gt;</span>
     <span class="hljs-tag">&lt;<span class="hljs-name">soapenv:Body</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">TransferFundsResponse</span>&gt;</span>
           <span class="hljs-tag">&lt;<span class="hljs-name">Status</span>&gt;</span>Success<span class="hljs-tag">&lt;/<span class="hljs-name">Status</span>&gt;</span>
           <span class="hljs-tag">&lt;<span class="hljs-name">TransactionID</span>&gt;</span>TXN987654<span class="hljs-tag">&lt;/<span class="hljs-name">TransactionID</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">TransferFundsResponse</span>&gt;</span>
     <span class="hljs-tag">&lt;/<span class="hljs-name">soapenv:Body</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">soapenv:Envelope</span>&gt;</span>
</code></pre>
</li>
</ul>
<p>Banks, healthcare providers, and government agencies use SOAP for secure, reliable APIs. Financial institutions process transactions with strict authentication, while healthcare systems exchange patient data under compliance regulations. Airlines rely on SOAP for booking and ticketing, ensuring consistent data integrity across systems.</p>
<h3 id="heading-graphql-apis">GraphQL APIs</h3>
<p>GraphQL is a query language and runtime for APIs developed by Facebook. It allows clients to request exactly the data they need in a single request, reducing over-fetching and under-fetching.</p>
<h4 id="heading-key-components-2">Key Components</h4>
<ol>
<li><p>Schema: This is the heart of a GraphQL API. It defines the structure of your data, including the types of objects, their fields, and their relationships. It acts as a contract between the client and server, specifying what data can be queried.</p>
</li>
<li><p>Types: These define the structure of objects in your data. They specify the fields that each object has and the data types of those fields.</p>
</li>
<li><p>Fields: These are the individual pieces of data that can be queried on an object.</p>
</li>
<li><p>Queries: These are requests from the client to retrieve data. They specify the fields that the client wants to recover.</p>
</li>
<li><p>Mutations: These are requests from the client to modify data (create, update, or delete).</p>
</li>
<li><p>Resolvers: These are functions that fetch the data for each field in the schema. They connect the GraphQL schema to the underlying data sources.</p>
</li>
<li><p>Subscriptions: These enable real-time updates. Clients can subscribe to specific events, and the server will push updates whenever they occur.</p>
</li>
</ol>
<h4 id="heading-operation-overview-2">Operation Overview</h4>
<p>GraphQL defines a schema that specifies available data types and their relationships. Clients then construct queries or mutations that precisely request the needed data fields. The GraphQL server processes these requests, using resolvers to fetch data from backend sources.</p>
<p>The server validates the request against the schema, executes the resolvers, and returns a JSON response containing only the requested data. Clients can establish subscriptions for real-time updates, enabling the server to push data changes as they occur. This approach minimises over-fetching and under-fetching, improving efficiency and flexibility in data retrieval.</p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXcmC7u4hu44TvJ603f9ODRYIgi3UiHMs-Q4qjE8FZqwPnEGDPTU6DhZSvLCZU3BO7WITNnuls_801ChJyACz6xpKOdvoQ5hLswAMIHZ3-Ii4dyg7CEKZ5m1AAgv70sso-c26Cl_sQ?key=2qCWq-hs7d172uM7WbtEHg_B" alt="Diagram from kinsta.com illustrating a GraphQL server architecture, showing the transfer of GraphQL Query request and JSON payload from the server." width="600" height="400" loading="lazy"></p>
<h4 id="heading-practical-examples-and-real-world-use-cases-1">Practical Examples and Real-world Use Cases</h4>
<p>Let’s explore how GraphQL APIs work practically by considering an E-commerce API powered by GraphQL. This API can efficiently fetch product details, reviews, and stock availability. The server is created using NodeJS and <a target="_blank" href="https://www.apollographql.com/docs/apollo-server">Apollo Server</a>. Creating the server is beyond the scope of this article, so we will focus on the Schema (how a relational database is structured and visually represented) and the <strong>Request</strong> and <strong>Response</strong> logic.</p>
<ol>
<li>Schema:</li>
</ol>
<pre><code class="lang-graphql"><span class="hljs-comment"># Schema (schema.graphql)</span>

<span class="hljs-keyword">type</span> Product {
  <span class="hljs-symbol">id:</span> ID!
  <span class="hljs-symbol">name:</span> String!
  <span class="hljs-symbol">description:</span> String
  <span class="hljs-symbol">price:</span> Float!
  <span class="hljs-symbol">inventory:</span> Int!
  <span class="hljs-symbol">category:</span> String!
}

<span class="hljs-keyword">type</span> Query {
  product(<span class="hljs-symbol">id:</span> ID!): Product
  products(<span class="hljs-symbol">category:</span> String): [Product!]!
}

<span class="hljs-keyword">type</span> Mutation {
  createProduct(<span class="hljs-symbol">name:</span> String!, <span class="hljs-symbol">description:</span> String, <span class="hljs-symbol">price:</span> Float!, <span class="hljs-symbol">inventory:</span> Int!, <span class="hljs-symbol">category:</span> String!): Product!
  updateProductInventory(<span class="hljs-symbol">id:</span> ID!, <span class="hljs-symbol">inventory:</span> Int!): Product!
}
</code></pre>
<p>The Schema defines the data types (<code>Product</code>, <code>Query</code>, <code>Mutation</code>) and specifies the available queries (<code>product</code>, <code>products</code>), and mutations (<code>createProduct</code>, <code>updateProductInventory</code>). It uses the <a target="_blank" href="https://graphql.org/learn/schema/">GraphQL type system</a> (String, Int, Float, ID, [ ], !)</p>
<ol start="2">
<li><p>Requests and Response</p>
<ul>
<li><p>Fetching product data - A client requests specific product fields (for example, name, price, and description):</p>
<pre><code class="lang-graphql">  <span class="hljs-keyword">query</span> {
    product(<span class="hljs-symbol">id:</span> <span class="hljs-string">"123"</span>) {
      name
      price
      description
    }
  }
</code></pre>
<p>  If it is successful, the server responds with only the requested data:</p>
<pre><code class="lang-json">  {
    <span class="hljs-attr">"data"</span>: {
      <span class="hljs-attr">"product"</span>: {
        <span class="hljs-attr">"name"</span>: <span class="hljs-string">"Wireless Headphones"</span>,
        <span class="hljs-attr">"price"</span>: <span class="hljs-number">99.99</span>,
        <span class="hljs-attr">"inStock"</span>: <span class="hljs-literal">true</span>
      }
    }
  }
</code></pre>
</li>
<li><p>Create a new product:</p>
<pre><code class="lang-graphql">  <span class="hljs-keyword">mutation</span> {
    createProduct(<span class="hljs-symbol">name:</span> <span class="hljs-string">"Mouse"</span>, <span class="hljs-symbol">price:</span> <span class="hljs-number">30</span>, <span class="hljs-symbol">inventory:</span> <span class="hljs-number">100</span>, <span class="hljs-symbol">category:</span> <span class="hljs-string">"Electronics"</span>) {
      id
      name
      price
    }
  }
</code></pre>
</li>
<li><p>Update product information:</p>
<pre><code class="lang-graphql">  <span class="hljs-keyword">mutation</span> {
    updateProduct(<span class="hljs-symbol">id:</span> <span class="hljs-string">"123"</span>, <span class="hljs-symbol">price:</span> <span class="hljs-number">89.99</span>) {
      name
      price
    }
  }
</code></pre>
<p>  If successful, the server returns the updated details:</p>
<pre><code class="lang-json">  {
    <span class="hljs-attr">"data"</span>: {
      <span class="hljs-attr">"updateProduct"</span>: {
        <span class="hljs-attr">"name"</span>: <span class="hljs-string">"Wireless Headphones"</span>,
        <span class="hljs-attr">"price"</span>: <span class="hljs-number">89.99</span>
      }
    }
  }
</code></pre>
</li>
</ul>
</li>
</ol>
<p>Companies like Facebook and Shopify use GraphQL for efficient, flexible APIs. E-commerce and social apps fetch only needed data, reducing over-fetching. Mobile apps optimize performance, while analytics tools aggregate complex data seamlessly.</p>
<h3 id="heading-grpc-apis">gRPC APIs</h3>
<p>Remote Procedure Call (gRPC) is a high-performance RPC framework that serialises structured data using HTTP/2 and Protocol Buffers. It supports synchronous and asynchronous communication and features like streaming.</p>
<p>HTTP/2 is the latest evolution of HTTP, designed with exciting features like binary framing, multiplexing, header compression, and server push to boost performance and reduce latency. gRPC takes full advantage of these capabilities, enabling quick, efficient, and simultaneous communication, which makes it a perfect fit for microservices and real-time applications.</p>
<h4 id="heading-key-components-3">Key Components</h4>
<ol>
<li><p>Service definition: This is defined in a .proto file. It specifies the services offered and the RPC methods available, acting as the contract between client and server.</p>
</li>
<li><p>Messages are data structures defined using Protocol Buffers, which efficiently serialise and deserialise data between systems.</p>
</li>
<li><p>Stubs: Auto-generated client and server code that lets the client call remote methods as if they were local and enables the server to implement the service logic.</p>
</li>
<li><p>Channels: These manage the connection between client and server, handling the underlying network communication.</p>
</li>
<li><p>RPC methods: gRPC supports different types of calls, including unary (single request-response), client streaming, server streaming, and bidirectional streaming, each suited for different use cases.</p>
</li>
<li><p>Interceptors and metadata: These provide mechanisms to add extra functionality, such as authentication, logging, and error handling, by attaching metadata to RPC calls.</p>
</li>
</ol>
<h4 id="heading-operation-overview-3">Operation Overview</h4>
<p>gRPC enables developers to define service contracts and message types in a .proto file with Protocol Buffers, serving as a blueprint for available RPC methods. The code generator produces client and server stubs, allowing remote procedures to be invoked like local functions, while channels manage HTTP/2-based network communication.</p>
<p>It supports unary, client streaming, server streaming, and bidirectional streaming for different data exchange patterns. Also, interceptors and metadata can be integrated for tasks like authentication and logging, keeping the system robust, secure, and efficient.</p>
<h4 id="heading-practical-examples-and-real-world-use-cases-2">Practical Examples and Real-world Use Cases</h4>
<p>Let’s consider a ride-sharing application that uses gRPC for fast communication between clients (mobile apps) and backend services. gRPC uses binary serialization via protocol buffers (Protobuf) instead of text-based formats like JSON or XML. This makes network communication significantly faster and more efficient.</p>
<ol>
<li>The .proto file defines the API structure:</li>
</ol>
<pre><code class="lang-json">syntax = <span class="hljs-string">"proto3"</span>;

service RideService {
  rpc RequestRide(RideRequest) returns (RideResponse);
  rpc StreamRideUpdates(RideUpdateRequest) returns (stream RideUpdate);
}

message RideRequest {
  string user_id = 1;
  string pickup_location = 2;
  string destination = 3;
}

message RideResponse {
  string ride_id = 1;
  string driver_name = 2;
  string car_model = 3;
}

message RideUpdate {
  string ride_id = 1;
  string status = 2;
  string driver_location = 3;
}

message RideUpdateRequest {
  string ride_id = 1;
}
</code></pre>
<p>When a client sends a <code>RideRequest</code>, it is serialized into a compact binary format using Protobuf. This reduces payload size, speeds up transmission, and improves efficiency. The server deserializes it back into a structured object before processing.</p>
<ol start="2">
<li><p>Request and Response:</p>
<ul>
<li><p>Requesting a ride: The client sends a ride request with the click of a button that entails:</p>
<pre><code class="lang-json">  {
    <span class="hljs-attr">"user_id"</span>: <span class="hljs-string">"U123"</span>,
    <span class="hljs-attr">"pickup_location"</span>: <span class="hljs-string">"Central Park"</span>,
    <span class="hljs-attr">"destination"</span>: <span class="hljs-string">"Times Square"</span>
  }
</code></pre>
<p>  The server responds with driver details:</p>
<pre><code class="lang-json">  {
    <span class="hljs-attr">"ride_id"</span>: <span class="hljs-string">"R456"</span>,
    <span class="hljs-attr">"driver_name"</span>: <span class="hljs-string">"John Doe"</span>,
    <span class="hljs-attr">"car_model"</span>: <span class="hljs-string">"Toyota Prius"</span>
  }
</code></pre>
<p>  You must be wondering why the requests and responses are displayed in JSON since gRPC doesn’t use text-based formats like JSON and XML. The compressed binary stream used in gRPC is not human-readable like JSON. It’s a compact, efficient encoding format that requires Protobuf deserialization under the hood to be understood. In compressed binary stream format, the request or response will look like this:</p>
<pre><code class="lang-markdown">  08 D2 04 12 0D 43 65 6E 74 72 61 6C 20 50 61 72 6B 1A 0B 54 69 6D 65 73 20 53 71 75 61 72 65
</code></pre>
</li>
<li><p>Streaming ride updates: Once a ride is assigned, the server streams real-time updates to the client:</p>
<pre><code class="lang-json">  {
    <span class="hljs-attr">"ride_id"</span>: <span class="hljs-string">"R456"</span>,
    <span class="hljs-attr">"status"</span>: <span class="hljs-string">"Driver on the way"</span>,
    <span class="hljs-attr">"driver_location"</span>: <span class="hljs-string">"5th Avenue"</span>
  }
</code></pre>
</li>
</ul>
</li>
</ol>
<p>Companies use gRPC for high-performance, real-time applications requiring efficient service communication. Tech giants like Google, Netflix, and Dropbox utilize gRPC for scalable microservices. Ride-sharing apps stream live driver locations, while fintech platforms manage secure, low-latency transactions. IoT systems and AI applications depend on gRPC for real-time data exchange and efficient interactions.</p>
<h2 id="heading-how-to-choose-an-api-architecture">How to Choose an API Architecture</h2>
<p>Selecting an API architecture involves balancing various factors, including performance, scalability, ease of use, and security, according to your project's specific needs.</p>
<p>REST is known for its simplicity and stateless design, which aids scalability and ease of use, but its security depends mainly on external measures like HTTPS and proper authentication mechanisms.</p>
<p>SOAP, while more complex, provides robust built-in security standards (like WS-Security) and reliable transactional support, making it suitable for enterprise environments.</p>
<p>GraphQL offers efficient data fetching and high performance by allowing clients to request only the data they need. Still, it may require additional security measures such as query depth limiting and proper authentication on the server side.</p>
<p>gRPC delivers exceptional performance and is ideal for microservices with real-time data needs. It leverages HTTP/2 and TLS for secure, efficient communication, though it has a steeper learning curve.</p>
<p>The table below summarises the features and tradeoffs between these architectures:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Feature</td><td>REST</td><td>SOAP</td><td>GraphQL</td><td>gRPC</td></tr>
</thead>
<tbody>
<tr>
<td>Performance</td><td>Moderate (Potential over-fetching of data)</td><td>Low</td><td>High</td><td>High</td></tr>
<tr>
<td>Scalability</td><td>High</td><td>Moderate</td><td>High</td><td>Very high (Efficient for microservices and real-time data)</td></tr>
<tr>
<td>Ease of use</td><td>Simple and widely adopted</td><td>Complex</td><td>Intuitive for clients (Server-side complexity may grow)</td><td>Steep learning curve</td></tr>
<tr>
<td>Security</td><td>Relies on external mechanisms (HTTPS, OAuth, and so on)</td><td>Strong built-in security via WS-Security and formal contracts</td><td>Requires additional measures (query validation, rate limiting)</td><td>High security with built-in TLS support and robust authentication protocols</td></tr>
</tbody>
</table>
</div><h2 id="heading-conclusion-and-future-trends">Conclusion and Future Trends</h2>
<p>APIs have become a mainstay in modern software development, facilitating seamless communication and data exchange between diverse applications. Their impact is undeniable, from public APIs that fuel innovation to private APIs that streamline internal processes.</p>
<p>Understanding the various API architectures, like REST, SOAP, GraphQL, and gRPC, empowers developers to select the optimal approach for their specific needs, balancing performance, scalability, and ease of use.</p>
<p>Looking ahead, the API landscape is set for exciting changes. With AI-driven APIs, decentralized architectures, and improved security measures, we’ll see new ways to build and interact with software. The continuous evolution of API standards and the growth of low-code/no-code platforms are making API development more accessible to everyone.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Stateful vs Stateless Architecture – Explained for Beginners ]]>
                </title>
                <description>
                    <![CDATA[ In programming, "state" refers to the condition of a system, component, or application at a particular point in time. As a simple example, if you are shopping on amazon.com, whether you are currently logged into the site or if you have anything store... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/stateful-vs-stateless-architectures-explained/</link>
                <guid isPermaLink="false">66d45e1d680e33282da25e61</guid>
                
                    <category>
                        <![CDATA[ architecture ]]>
                    </category>
                
                    <category>
                        <![CDATA[ State Management  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Daniel Adetunji ]]>
                </dc:creator>
                <pubDate>Mon, 21 Aug 2023 21:08:59 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/08/cover-photo.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In programming, "state" refers to the condition of a system, component, or application at a particular point in time.</p>
<p>As a simple example, if you are shopping on amazon.com, whether you are currently logged into the site or if you have anything stored in your cart are some examples of state.</p>
<p>State represents the data that is stored and used to keep track of the current status of the application. Understanding and managing state is crucial for building interactive and dynamic web applications.</p>
<p>The concept of a “state” crosses many boundaries in architecture. Design patterns (like REST and GraphQL), protocols (like HTTP and TCP), firewalls and functions can be stateful or stateless. But the underlying principle of “state” cutting across all of these domains remains the same.</p>
<p>This article will explain what state means. It will also explain stateful and stateless architectures with some analogies and the benefits and tradeoffs of both.</p>
<h2 id="heading-what-is-stateful-architecture">What is Stateful Architecture?</h2>
<p>Imagine you go to a pizza restaurant to eat some food. In this restaurant, there is only a single waiter, and the waiter takes detailed notes on your table number, what you ordered, your preferences based on past orders, like what type of pizza crust you like or toppings you are allergic to, and so on.</p>
<p><img src="https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3d2bd50-8945-4fb4-b36a-1d4730beebe5_1726x1080.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Illustration of a waiter taking a person's order at a pizza restaurant</em></p>
<p>All of these pieces of information that the waiter writes down in their notepad are the customer's state. Only the waiter serving you has access to this information. If you want to make a change to your order or check how its coming along, you need to speak to the same waiter that took your order. But since there is only one waiter, that is not a problem.</p>
<p>Now, suppose the restaurant starts to get busier. Your waiter has to respond to other guests so more waiters are called to work. You now want to check the status of your order and make a small change to it – a plain crust instead of a cheesy crust. The only available waiter is different from the one who initially took your order.</p>
<p><img src="https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b483849-6dc8-4a90-a491-199150d71547_1566x1020.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Illustration showing a different waiter being unable to help the customer change their order</em></p>
<p>This new waiter does not have details of your order, that is your state. Naturally, they will not be able to check the status of your order or make changes to it. A restaurant that operates like this, where only the waiter that initially took your order can give you updates about it, or make changes to it, follows a stateful design.</p>
<p>Similarly, a stateful application will have a server that remembers clients' data (that is, their state). All future requests will be routed to the same server using a load balancer with sticky sessions enabled. In this way, the server is always aware of the client.</p>
<p>The diagram below shows two different users trying to access a web server through a load balancer. Since the application state is maintained on the servers, the users must always be routed to the same server for every single request in order to preserve state.</p>
<p><img src="https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd494a45c-284b-4dd8-a6f1-5eb072157c70_1028x834.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Diagram showing how a stateful application works</em></p>
<p>Sticky sessions is a configuration that allows the load balancer to route a user's requests consistently to the same backend server for the duration of their session. This is in contrast to <a target="_blank" href="https://lightcloud.substack.com/i/102200211/load-balancing-explained">traditional load balancing</a>, where requests from a user can be directed to any available backend server in a round-robin or other load distribution pattern.</p>
<p>What is the problem with a stateful architecture? Imagine a restaurant run in this manner. While it may be ideal and easy to implement for a small, family run restaurant with only a few customers, such a design is <strong>not fault tolerant</strong> and <strong>not scalable</strong>.</p>
<p>What happens if the waiter who took a customer's order has an emergency and needs to leave? All the information regarding that order leaves with that waiter as well. This disrupts the customer’s experience, since any new waiter brought in to replace the old one has no knowledge of previous orders. This is a design that is not fault tolerant.</p>
<p>Also, having to distribute requests so that the same customer can only speak to the same waiter means that the load on different waiters is not equally distributed. Some waiters will be overwhelmed with requests if you have a very demanding customer who always modifies or adds things to their order. Some of the other waiters will have nothing to do, and can’t step in to help. Again, this is a non scalable design.</p>
<p>Similarly, storing state data for different customers on different servers is not fault tolerant and not scalable. A server failure will lead to loss of state data. So, if a user is logged in and about to checkout for a large order on Amazon.com for example, the user will be forced to re-authenticate and the user's basket will be empty. They would have to log in again and fill up their basket from scratch – a poor user experience.</p>
<p>Scalability will also be difficult to achieve during peak times like Black Friday with a stateful design. New servers will be added to the <a target="_blank" href="https://lightcloud.substack.com/i/102200211/auto-scaling-explained">auto scaling group</a> but since sticky sessions are enabled, clients will be routed to the same server, causing them to be overwhelmed, which can cause an increase in response times - a poor user experience.</p>
<p>Stateless architectures solve a lot of these problems.</p>
<h2 id="heading-what-is-stateless-architecture">What is Stateless Architecture?</h2>
<p>“Stateless” architecture is a confusing term, as it implies the system is without state. A stateless architecture does not, however, mean that state information is not stored. It simply means that state information is stored outside of the server. Therefore, the state of being stateless only applies to the server.</p>
<p>Bringing back the restaurant analogy, waiters in a stateless restaurant can be thought of as having perfectly forgetful memories. They do not recognise old customers, and can’t recall what you ordered or how you like your pizza. They will simply take note of customers' orders on a separate system, say a computer, that is accessible by all the waiters. They can then revert back to the computer to get details of an order and make changes to it as required.</p>
<p><img src="https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3bc5ab03-b96a-4e4b-b27e-ad9077a4bdc3_1852x932.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Illustration of a "forgetful" waiter taking an order and then consulting the computer about orders</em></p>
<p>By storing the ‘state’ of a customer's order on a central system accessible by other waiters, any waiter can serve any customer.</p>
<p>In a stateless architecture, HTTP requests from a client can be sent to any of the servers.</p>
<p>State is typically stored on a separate database, accessible by all the servers. This creates a fault tolerant and scalable architecture since web servers can be added or removed as needed, without impacting state data.</p>
<p>The load will also be equally distributed across all servers, since the load balancer will not need a sticky session configuration to route the same clients to the same servers.</p>
<p>The diagram below shows two different users trying to access a web server through a load balancer. Since the application state is maintained separately from the servers, the users can be routed to any of the servers, which will then get the state information from an external database accessible by both servers.</p>
<p><img src="https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F360b7c09-6e3c-4443-a05b-b58f70dc0039_1322x804.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Illustration showing a diagram of stateless architecture</em></p>
<p>Typically, state data is stored in a cache like <a target="_blank" href="https://redis.io/">Redis</a>, an in-memory data store. Storing state data in-memory improves read and write times, compared to storing it on disk, as explained <a target="_blank" href="https://lightcloud.substack.com/i/81969975/compute-memory-and-storage-an-analogy">here</a>.</p>
<h2 id="heading-bringing-it-together">Bringing it Together</h2>
<p>This article has described how stateful and stateless web applications work and the trade-offs of both. But the principle of statefulness and statelessness apply beyond web applications.</p>
<p>If we look at network protocols as an example, HTTP is a stateless protocol. This means that each HTTP request from a client to a server is <strong>independent</strong> and carries <strong>no knowledge of previous requests</strong> or their context. The server treats each request as a separate and isolated transaction, and it doesn't inherently maintain information about the state of the client between requests.</p>
<p>State is either maintained on the servers (stateful architecture) or in a separate database outside the servers (stateless architecture). The HTTP protocol itself does not maintain state.</p>
<p>Unlike the stateless nature of HTTP, <a target="_blank" href="https://www.freecodecamp.org/news/tcp-vs-udp/">the TCP protocol</a> is connection-oriented and stateful. It establishes a connection between two devices (usually a client and a server) and maintains a continuous communication channel until the connection is terminated.</p>
<p>The same logic applies to firewalls as well, which can be stateful or stateless.</p>
<p>In AWS, a security group is a virtual firewall that controls inbound and outbound traffic for virtual machines or instances within a cloud environment. Security groups are stateful. When you allow a specific incoming traffic flow, the corresponding outgoing traffic flow is automatically allowed as well. In other words, the state of the connection is tracked.</p>
<p>Network Access Control Lists (NACLs) are used to control inbound and outbound traffic at the subnet level in AWS. NACLs are stateless. Being stateless means that you must explicitly define rules for both incoming and outgoing traffic.</p>
<p>Unlike security groups, where response traffic is automatically allowed when you allow incoming traffic, NACLs require you to define separate rules for inbound and outbound traffic.</p>
<p>Functions and design patterns can also be stateful or stateless.</p>
<p>The key principle behind something that is stateful is that it has perfect memory or knowledge of previous calls or requests, while something that is stateless has no memory or knowledge of previous calls or requests.</p>
<p>Hopefully you now have a good grasp of how stateful and stateless applications work and can decide which option is best for your applications.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Learn Network Architecture Basics for Beginners ]]>
                </title>
                <description>
                    <![CDATA[ Networking is engineering, magic, and skilled trade all rolled into one. Getting all the countless pieces to talk nicely – and reliably – to each other is complicated. Troubleshooting unexpected outages is worse.  But, once you've got it all running ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/network-architecture-basics/</link>
                <guid isPermaLink="false">66b99616d9d170feecefbba3</guid>
                
                    <category>
                        <![CDATA[ architecture ]]>
                    </category>
                
                    <category>
                        <![CDATA[ computer network ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Security ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ David Clinton ]]>
                </dc:creator>
                <pubDate>Tue, 11 Apr 2023 19:05:27 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/04/pexels-brett-sayles-2881232.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Networking is engineering, magic, and skilled trade all rolled into one. Getting all the countless pieces to talk nicely – and reliably – to each other is complicated. Troubleshooting unexpected outages is worse. </p>
<p>But, once you've got it all running nicely, well that's when you should really be worried: because that's exactly when the bad guys start banging away at the door trying to find a way in.</p>
<p>In this article we're going to cover just enough of the most important networking fundamentals so that discussions of network security that you may encounter will make sense. </p>
<p>This article comes from <a target="_blank" href="https://www.udemy.com/course/complete-lpi-security-essentials-exam-study-guide/?referralCode=C2B6802EDB99578238B5">The Complete LPI Security Essentials Exam Study Guide</a>. You can also follow along using this video:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/tsAEFWVJKsc" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-understanding-ipv4-and-nat-routing">Understanding IPv4 and NAT Routing</h2>
<p>IP networks (where IP stands for Internet Protocol) are the backbone of the Internet, connecting devices and transmitting data over the network.</p>
<p>IP is responsible for routing data packets from one device to another, and IP version 4 is the most widely used IP address format. IPv4 uses a 32-bit address, and consists of four 8-bit numbers called octets. IPv4 addresses are written in a decimal notation where each octet is separated by a dot.</p>
<p>An example of an IPv4 host address might look something like this:</p>
<pre><code><span class="hljs-number">192.168</span><span class="hljs-number">.2</span><span class="hljs-number">.34</span>
</code></pre><p>Network Address Translation is a method used to allow private IPv4 addresses to access the Internet. NAT maps private IP addresses to a single public IP address, which is assigned by an Internet Service Provider (ISP). </p>
<p>When a device in a private network wants to access the Internet, it sends a request to the NAT gateway. The NAT gateway translates the private IP address of the device into the public IP address assigned by the ISP and forwards the request to the Internet.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/slide-11.png" alt="Image" width="600" height="400" loading="lazy">
<em>NAT addressing explained in a diagram</em></p>
<p>When the response from the Internet is received, the NAT gateway translates the public IP address back into the private IP address of the device and sends the response to the device. </p>
<p>In this way, NAT enables multiple devices in a private network to share a single public IP address and access the Internet, while hiding their private IP addresses from the public. NAT also provides a basic level of security by hiding the internal network from the Internet.</p>
<h2 id="heading-understanding-ipv6">Understanding IPv6</h2>
<p>IP version 6 is the latest IP address format. IPv6 uses a 128-bit address, and is made up of eight 16-bit hexadecimal segments separated by colons.</p>
<p>Here is an example of what an IPv6 address might look like:</p>
<pre><code><span class="hljs-number">2001</span>:<span class="hljs-number">0</span>db8:<span class="hljs-number">85</span>a3:<span class="hljs-number">0000</span>:<span class="hljs-number">0000</span>:<span class="hljs-number">8</span>a2e:<span class="hljs-number">0370</span>:<span class="hljs-number">7334</span>
</code></pre><p>IPv6 was created because we were running out of IPv4 addresses – since IPv4's 32-bit addresses allow for a maximum of only 4.3 billion unique addresses. </p>
<p>This was great in the early days of the Internet, but as the number of Internet-connected devices has grown, the demand for unique IP addresses has surpassed the number available in the IPv4 address space.</p>
<p>To address this shortage, IPv6 was developed with its larger address space, allowing for 340 trillion, trillion, trillion unique addresses. This large address space ensures that there will be enough unique IP addresses for all Internet-connected devices forever. Literally.</p>
<p>Additionally, IPv6 addresses overcome some other limitations of IPv4, such as improved security, auto-configuration, and support for hierarchical address allocation and routing.</p>
<h2 id="heading-defining-routing-protocols">Defining Routing Protocols</h2>
<p>TCP (Transmission Control Protocol) and UDP (User Datagram Protocol) are two of the most common transport layer protocols used in IP networks. </p>
<p>TCP is a reliable connection-oriented protocol that provides error-checking and flow control. UDP is a connectionless protocol that provides fast data transmission but with less reliability.</p>
<p>ICMP (Internet Control Message Protocol) is a network layer protocol used to send error messages, test network connectivity (in particular, through a tool called <code>ping</code>), and perform other functions.</p>
<p>DHCP (Dynamic Host Configuration Protocol) is a protocol used to dynamically assign IP addresses to devices on a network. In a home or small business network, DHCP is usually performed by a router or a dedicated DHCP server, which is responsible for dynamically assigning IP addresses to devices on the network.</p>
<p>Here's how the process of DHCP typically works:</p>
<ul>
<li>When a device connects to the network, it broadcasts a request for an IP address.</li>
<li>The DHCP server receives the request and assigns a unique IP address to the device, along with other network information such as the subnet mask, default gateway, and DNS server addresses.</li>
<li>The device receives the assigned IP address and other network information from the DHCP server and uses it to configure its network settings.</li>
<li>Finally, the DHCP server maintains a table of assigned IP addresses and the devices that have been assigned them, so it can ensure that each device on the network has a unique IP address.</li>
</ul>
<p>In a home or small business network, the router or DHCP server is usually configured to automatically assign IP addresses to devices on the network. This eliminates the need for manual IP address configuration and makes it easy for devices to connect to the network.</p>
<p>With those basics, you'll be in a much better position to understand the stuff you hear and read about network security issues. </p>
<p>This article and the accompanying video are excerpted from <a target="_blank" href="https://www.udemy.com/course/complete-lpi-security-essentials-exam-study-guide/?referralCode=C2B6802EDB99578238B5">my Complete LPI Security Essentials Exam Study Guide course</a>. And there's much more technology goodness available at <a target="_blank" href="https://bootstrap-it.com/">bootstrap-it.com</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ JVM Tutorial - Java Virtual Machine Architecture Explained for Beginners ]]>
                </title>
                <description>
                    <![CDATA[ By Siben Nayak Whether you have used Java to develop programs or not, you might have heard about the Java Virtual Machine (JVM) at some point or another.  JVM is the core of the Java ecosystem, and makes it possible for Java-based software programs t... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/jvm-tutorial-java-virtual-machine-architecture-explained-for-beginners/</link>
                <guid isPermaLink="false">66d46155182810487e0ce1bc</guid>
                
                    <category>
                        <![CDATA[ architecture ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Java ]]>
                    </category>
                
                    <category>
                        <![CDATA[ virtual machine ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Fri, 08 Jan 2021 23:35:48 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/01/JVM.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Siben Nayak</p>
<p>Whether you have used Java to develop programs or not, you might have heard about the Java Virtual Machine (JVM) at some point or another. </p>
<p>JVM is the core of the Java ecosystem, and makes it possible for Java-based software programs to follow the <em>"write once, run anywhere"</em> approach. You can write Java code on one machine, and run it on any other machine using the JVM.</p>
<p>JVM was initially designed to support only Java. However, over the time, many other languages such as Scala, Kotlin and Groovy were adopted on the Java platform. All of these languages are collectively known as JVM languages.</p>
<p>In this article, we will learn more about the JVM, how it works, and the various components that it is made of.</p>
<p>#What is a Virtual Machine?</p>
<p>Before we jump into the JVM, let's revisit the concept of a Virtual Machine (VM).</p>
<p>A virtual machine is a <em>virtual representation of a physical computer</em>. We can call the virtual machine the guest machine, and the physical computer it runs on is the host machine.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/01/image-37.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>A single physical machine can run multiple virtual machines, each with their own operating system and applications. These virtual machines are isolated from each other.</p>
<p>#What is the Java Virtual Machine?</p>
<p>In programming languages like C and C++, the code is first compiled into platform-specific machine code. These languages are called <em>compiled languages</em>. </p>
<p>On the other hand, in languages like JavaScript and Python, the computer executes the instructions directly without having to compile them. These languages are called <em>interpreted languages</em>.</p>
<p>Java uses a combination of both techniques. Java code is first compiled into byte code to generate a <em>class</em> file. This <em>class</em> file is then interpreted by the Java Virtual Machine for the underlying platform. The same <em>class</em> file can be executed on any version of JVM running on any platform and operating system.</p>
<p><em>Similar to virtual machines,</em> the JVM creates an isolated space on a host machine. This space can be used to execute Java programs irrespective of the platform or operating system of the machine.</p>
<p>#Java Virtual Machine Architecture</p>
<p>The JVM consists of three distinct components:</p>
<ol>
<li>Class Loader</li>
<li>Runtime Memory/Data Area</li>
<li>Execution Engine</li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/01/image-39.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Let's take a look at each of them in more detail.</p>
<h2 id="heading-class-loader">Class Loader</h2>
<p>When you compile a <code>.java</code> source file, it is converted into byte code as a <code>.class</code> file. When you try to use this class in your program, the class loader loads it into the main memory. </p>
<p>The first class to be loaded into memory is usually the class that contains the <code>main()</code> method.</p>
<p>There are three phases in the class loading process: loading, linking, and initialization.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/01/image-40.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-loading">Loading</h3>
<p>Loading involves taking the binary representation (bytecode) of a class or interface with a particular name, and generating the original class or interface from that.</p>
<p>There are three built-in class loaders available in Java:</p>
<ul>
<li><strong>Bootstrap Class Loader</strong> <strong>-</strong> This is the root class loader. It is the superclass of Extension Class Loader and loads the standard Java packages like <code>java.lang</code>, <code>java.net</code>, <code>java.util</code>, <code>java.io</code>, and so on. These packages are present inside the <code>rt.jar</code> file and other core libraries present in the <code>$JAVA_HOME/jre/lib</code> directory.</li>
<li><strong>Extension Class Loader -</strong> This is the subclass of the Bootstrap Class Loader and the superclass of the Application Class Loader. This loads the extensions of standard Java libraries which are present in the <code>$JAVA_HOME/jre/lib/ext</code> directory. </li>
<li><strong>Application Class Loader -</strong> This is the final class loader and the subclass of Extension Class Loader. It loads the files present on the classpath. By default, the classpath is set to the current directory of the application. The classpath can also be modified by adding the <code>-classpath</code> or <code>-cp</code> command line option.</li>
</ul>
<p>The JVM uses the <code>ClassLoader.loadClass()</code> method for loading the class into memory. It tries to load the class based on a fully qualified name. </p>
<p>If a parent class loader is unable to find a class, it delegates the work to a child class loader. If the last child class loader isn't able to load the class either, it throws <code>NoClassDefFoundError</code> or <code>ClassNotFoundException</code><em>.</em> </p>
<h3 id="heading-linking">Linking</h3>
<p>After a class is loaded into memory, it undergoes the linking process. Linking a class or interface involves combining the different elements and dependencies of the program together. </p>
<p>Linking includes the following steps:</p>
<p><strong>Verification:</strong> This phase checks the structural correctness of the <code>.class</code> file by checking it against a set of constraints or rules. If verification fails for some reason, we get a <code>VerifyException</code>.</p>
<p>For example, if the code has been built using Java 11, but is being run on a system that has Java 8 installed, the verification phase will fail.</p>
<p><strong>Preparation:</strong> In this phase, the JVM allocates memory for the static fields of a class or interface, and initializes them with default values. </p>
<p>For example, assume that you have declared the following variable in your class:</p>
<pre><code class="lang-java"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">boolean</span> enabled = <span class="hljs-keyword">true</span>;
</code></pre>
<p>During the preparation phase, JVM allocates memory for the variable <code>enabled</code>     and sets its value to the default value for a boolean, which is <code>false</code>.</p>
<p><strong>Resolution:</strong> In this phase, symbolic references are replaced with direct references present in the runtime constant pool. </p>
<p>For example, if you have references to other classes or constant variables present in other classes, they are resolved in this phase and replaced with their actual references.</p>
<h3 id="heading-initialization">Initialization</h3>
<p>Initialization involves executing the initialization method of the class or interface (known as <code>&lt;clinit&gt;</code>). This can include calling the class's constructor, executing the static block, and assigning values to all the static variables. This is the final stage of class loading.</p>
<p>For example, when we declared the following code earlier:</p>
<pre><code class="lang-java"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">boolean</span> enabled = <span class="hljs-keyword">true</span>;
</code></pre>
<p>The variable <code>enabled</code> was set to its default value of <code>false</code> during the preparation phase. In the initialization phase, this variable is assigned its actual value of <code>true</code>.</p>
<p><strong>Note:</strong> the JVM is multi-threaded. It can happen that multiple threads are trying to initialize the same class at the same time. This can lead to concurrency issues. You need to handle thread safety to ensure that the program works properly in a multi-threaded environment.</p>
<h2 id="heading-runtime-data-area">Runtime Data Area</h2>
<p>There are five components inside the runtime data area:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/01/image-32.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Let's look at each one individually.</p>
<h3 id="heading-method-area">Method Area</h3>
<p>All the class level data such as the run-time constant pool, field, and method data, and the code for methods and constructors, are stored here. </p>
<p>If the memory available in the method area is not sufficient for the program startup, the JVM throws an <code>OutOfMemoryError</code>.</p>
<p>For example, assume that you have the following class definition:</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Employee</span> </span>{

  <span class="hljs-keyword">private</span> String name;
  <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> age;

  <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Employee</span><span class="hljs-params">(String name, <span class="hljs-keyword">int</span> age)</span> </span>{

    <span class="hljs-keyword">this</span>.name = name;
    <span class="hljs-keyword">this</span>.age = age;
  }
}
</code></pre>
<p>In this code example, the field level data such as <code>name</code> and <code>age</code> and the constructor details are loaded into the method area.</p>
<p>The method area is created on the virtual machine start-up, and there is only one method area per JVM.</p>
<h3 id="heading-heap-area">Heap Area</h3>
<p>All the objects and their corresponding instance variables are stored here. This is the run-time data area from which memory for all class instances and arrays is allocated. </p>
<p>For example assume that you are declaring the following instance:</p>
<pre><code class="lang-java">Employee employee = <span class="hljs-keyword">new</span> Employee();
</code></pre>
<p>In this code example, an instance of <code>Employee</code> is created and loaded into the heap area.</p>
<p>The heap is created on the virtual machine start-up, and there is only one heap area per JVM.</p>
<p><strong>Note:</strong> Since the Method and Heap areas share the same memory for multiple threads, the data stored here is not thread safe.</p>
<h3 id="heading-stack-area">Stack Area</h3>
<p>Whenever a new thread is created in the JVM, a separate runtime stack is also created at the same time. All local variables, method calls, and partial results are stored in the stack area. </p>
<p>If the processing being done in a thread requires a larger stack size than what's available, the JVM throws a <code>StackOverflowError</code>.</p>
<p>For every method call, one entry is made in the stack memory which is called the Stack Frame. When the method call is complete, the Stack Frame is destroyed.</p>
<p>The Stack Frame is divided into three sub-parts:</p>
<ul>
<li><strong>Local Variables –</strong> Each frame contains an array of variables known as its <em>local variables</em>. All local variables and their values are stored here. The length of this array is determined at compile-time.</li>
<li><strong>Operand Stack –</strong> Each frame contains a last-in-first-out (LIFO) stack known as its <em>operand stack</em>. This acts as a runtime workspace to perform any intermediate operations. The maximum depth of this stack is determined at compile-time.</li>
<li><strong>Frame Data –</strong> All symbols corresponding to the method are stored here. This also stores the catch block information in case of exceptions.</li>
</ul>
<p>For example assume that you have the following code:</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">double</span> <span class="hljs-title">calculateNormalisedScore</span><span class="hljs-params">(List&lt;Answer&gt; answers)</span> </span>{

  <span class="hljs-keyword">double</span> score = getScore(answers);
  <span class="hljs-keyword">return</span> normalizeScore(score);
}

<span class="hljs-function"><span class="hljs-keyword">double</span> <span class="hljs-title">normalizeScore</span><span class="hljs-params">(<span class="hljs-keyword">double</span> score)</span> </span>{

  <span class="hljs-keyword">return</span> (score – minScore) / (maxScore – minScore);
}
</code></pre>
<p>In this code example, variables like <code>answers</code> and <code>score</code> are placed in the Local Variables array. The Operand Stack contains the variables and operators required to perform the mathematical calculations of subtraction and division.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/01/image-36.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><strong>Note:</strong> Since the Stack Area is not shared, it is inherently thread safe. </p>
<h3 id="heading-program-counter-pc-registers">Program Counter (PC) Registers</h3>
<p>The JVM supports multiple threads at the same time. Each thread has its own PC Register to hold the address of the currently executing JVM instruction. Once the instruction is executed, the PC register is updated with the next instruction.</p>
<h3 id="heading-native-method-stacks">Native Method Stacks</h3>
<p>The JVM contains stacks that support <em>native</em> methods. These methods are written in a language other than the Java, such as C and C++. For every new thread, a separate native method stack is also allocated.</p>
<h2 id="heading-execution-engine">Execution Engine</h2>
<p>Once the bytecode has been loaded into the main memory, and details are available in the runtime data area, the next step is to run the program. The Execution Engine handles this by executing the code present in each class.</p>
<p>However, before executing the program, the bytecode needs to be converted into machine language instructions. The JVM can use an interpreter or a JIT compiler for the execution engine.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/01/image-33.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-interpreter">Interpreter</h3>
<p>The interpreter reads and executes the bytecode instructions line by line. Due to the line by line execution, the interpreter is comparatively slower. </p>
<p>Another disadvantage of the interpreter is that when a method is called multiple times, every time a new interpretation is required.</p>
<h3 id="heading-jit-compiler">JIT Compiler</h3>
<p>The JIT Compiler overcomes the disadvantage of the interpreter. The Execution Engine first uses the interpreter to execute the byte code, but when it finds some repeated code, it uses the JIT compiler. </p>
<p>The JIT compiler then compiles the entire bytecode and changes it to native machine code. This native machine code is used directly for repeated method calls, which improves the performance of the system. </p>
<p>The JIT Compiler has the following components:</p>
<ol>
<li><strong>Intermediate Code Generator -</strong> generates intermediate code</li>
<li><strong>Code Optimizer -</strong> optimizes the intermediate code for better performance</li>
<li><strong>Target Code Generator -</strong> converts intermediate code to native machine code</li>
<li><strong>Profiler -</strong> finds the hotspots (code that is executed repeatedly)</li>
</ol>
<p>To better understand the difference between interpreter and JIT compiler, assume that you have the following code:</p>
<pre><code class="lang-java"><span class="hljs-keyword">int</span> sum = <span class="hljs-number">10</span>;
<span class="hljs-keyword">for</span>(<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span> ; i &lt;= <span class="hljs-number">10</span>; i++) {
   sum += i;
}
System.out.println(sum);
</code></pre>
<p>An interpreter will fetch the value of <code>sum</code> from memory for each iteration in the loop, add the value of <code>i</code> to it, and write it back to memory. This is a costly operation because it is accessing the memory each time it enters the loop.</p>
<p>However, the JIT compiler will recognize that this code has a HotSpot, and will perform optimizations on it. It will store a local copy of <code>sum</code> in the PC register for the thread and will keep adding the value of <code>i</code> to it in the loop. Once the loop is complete, it will write the value of <code>sum</code> back to memory.</p>
<p><strong>Note:</strong> a JIT compiler takes more time to compile the code than for the interpreter to interpret the code line by line. If you are going to run a program only once, using the interpreter is better.</p>
<h3 id="heading-garbage-collector">Garbage Collector</h3>
<p>The Garbage Collector (GC) collects and removes unreferenced objects from the heap area. It is the process of reclaiming the runtime unused memory automatically by destroying them. </p>
<p>Garbage collection makes Java memory efficient because because it removes the unreferenced objects from heap memory and makes free space for new objects. It involves two phases:</p>
<ol>
<li><strong>Mark -</strong> in this step, the GC identifies the unused objects in memory</li>
<li><strong>Sweep -</strong> in this step, the GC removes the objects identified during the previous phase</li>
</ol>
<p>Garbage Collections is done automatically by the JVM at regular intervals and does not need to be handled separately. It can also be triggered by calling <code>System.gc()</code>, but the execution is not guaranteed. </p>
<p>The JVM contains 3 different types of garbage collectors:</p>
<ol>
<li><strong>Serial GC -</strong> This is the simplest implementation of GC, and is designed for small applications running on single-threaded environments. It uses a single thread for garbage collection. When it runs, it leads to a "stop the world" event where the entire application is paused. The JVM argument to use Serial Garbage Collector is <code>-XX:+UseSerialGC</code></li>
<li><strong>Parallel GC -</strong> This is the default implementation of GC in the JVM, and is also known as Throughput Collector. It uses multiple threads for garbage collection, but still pauses the application when running. The JVM argument to use Parallel Garbage Collector is <code>-XX:+UseParallelGC</code>.</li>
<li><strong>Garbage First (G1) GC -</strong> G1GC was designed for multi-threaded applications that have a large heap size available (more than 4GB). It partitions the heap into a set of equal size regions, and uses multiple threads to scan them. G1GC identifies the regions with the most garbage and performs garbage collection on that region first. The JVM argument to use G1 Garbage Collector is <code>-XX:+UseG1GC</code></li>
</ol>
<p><strong>Note:</strong> There is another type of garbage collector called <strong>Concurrent Mark Sweep (CMS) GC</strong>. However, it has been deprecated since Java 9 and completely removed in Java 14 in favour of G1GC.</p>
<h2 id="heading-java-native-interface-jni">Java Native Interface (JNI)</h2>
<p>At times, it is necessary to use native (non-Java) code (for example, C/C++). This can be in cases where we need to interact with hardware, or to overcome the memory management and performance constraints in Java. Java supports the execution of native code via the Java Native Interface (JNI). </p>
<p>JNI acts as a bridge for permitting the supporting packages for other programming languages such as C, C++, and so on. This is especially helpful in cases where you need to write code that is not entirely supported by Java, like some platform specific features that can only be written in C.</p>
<p>You can use the <code>native</code> keyword to indicate that the method implementation will be provided by a native library. You will also need to invoke <code>System.loadLibrary()</code> to load the shared native library into memory, and make its functions available to Java.</p>
<h2 id="heading-native-method-libraries">Native Method Libraries</h2>
<p>Native Method Libraries are libraries that are written in other programming languages, such as C, C++, and assembly. These libraries are usually present in the form of <code>.dll</code> or <code>.so</code> files. These native libraries can be loaded through JNI.</p>
<p>#Common JVM Errors</p>
<ul>
<li><strong>ClassNotFoundExcecption</strong> - This occurs when the Class Loader is trying to load classes using <code>Class.forName()</code>, <code>ClassLoader.loadClass()</code> or <code>ClassLoader.findSystemClass()</code> but no definition for the class with the specified name is found.</li>
<li><strong>NoClassDefFoundError</strong> - This occurs when a compiler has successfully compiled the class, but the Class Loader is not able to locate the class file at the runtime.</li>
<li><strong>OutOfMemoryError</strong> - This occurs when the JVM cannot allocate an object because it is out of memory, and no more memory could be made available by the garbage collector.</li>
<li><strong>StackOverflowError</strong> - This occurs if the JVM runs out of space while creating new stack frames while processing a thread.</li>
</ul>
<p>#Conclusion</p>
<p>In this article, we discussed the Java Virtual Machine's architecture and its various components. Often we do not dig deep into the internal mechanics of the JVM or care about how it works while our code is working. </p>
<p>It is only when something goes wrong, and we need to tweak the JVM or fix a memory leak, that we try to understand its internal mechanics.</p>
<p>This is also a very popular interview question, both at junior and senior levels for backend roles. A deep understanding of the JVM helps you write better code and avoid pitfalls related to stack and memory errors.</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/jnpuRvRdTgI" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p>Thank you for staying with me so far. Hope you liked the article. You can connect with me on <a target="_blank" href="https://www.linkedin.com/in/theawesomenayak/">LinkedIn</a> where I regularly discuss technology and life. Also take a look at some of <a target="_blank" href="https://www.freecodecamp.org/news/author/theawesomenayak/">my other articles</a> and my <a target="_blank" href="https://www.youtube.com/channel/UCmWAaPgfWAkl-Jep5mY-NNg?sub_confirmation=1">YouTube channel</a>. Happy reading. 🙂</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Develop a Reusable eCommerce Platform ]]>
                </title>
                <description>
                    <![CDATA[ By Ramón Morcillo This is a story about my team’s hard work developing not a single eCommerce platform, but a reusable one for different owners. We kept the same codebase, look, and feel, and made it highly customizable.  I will conclude with what we... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/develop-a-reusable-ecommerce-platform/</link>
                <guid isPermaLink="false">66d460c54bc8f441cb6df81f</guid>
                
                    <category>
                        <![CDATA[ architecture ]]>
                    </category>
                
                    <category>
                        <![CDATA[ ecommerce ]]>
                    </category>
                
                    <category>
                        <![CDATA[ GraphQL ]]>
                    </category>
                
                    <category>
                        <![CDATA[ software development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ teamwork ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Wed, 30 Dec 2020 19:48:43 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/12/plants.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Ramón Morcillo</p>
<p>This is a story about my team’s hard work developing not a single eCommerce platform, but a reusable one for different owners. We kept the same codebase, look, and feel, and made it highly customizable. </p>
<p>I will conclude with what we learned from the process. I think our takeaways will be a useful learning resource for other software developers out there (and for ourselves in future projects, as well).</p>
<p>I will try to focus on the relevant parts as much as possible to make it easier to understand. Having said this, a bit of background is needed to go through this article.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li>Context of the project</li>
<li>The first MVP</li>
<li>Implementing GraphQL</li>
<li>Architecture and Tech Stack</li>
<li>The second MVP</li>
<li>Conclusion and lessons learned</li>
<li>Final thoughts</li>
</ul>
<h2 id="heading-context-of-the-project">Context of the project</h2>
<p>The client we were developing the platform for was an eLearning company which was composed of 3 main sub-companies.</p>
<p>For the past few years, the sub-companies had been operating mostly independently. But now they were trying to create a standardized way of doing things, so they could grow together in the best way.</p>
<p>The project was an ambitious one. Creating an ecommerce platform that would work for all the sub-companies wasn’t easy to design or to implement. There were a large number of unsolved questions they had, which made it very hard to estimate.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/12/doubts-2.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-the-first-mvp">The first MVP</h2>
<p>To tackle this difficult challenge, we started from the bottom with one of the 3 sub-companies – let’s call it sub-company H. In fact, it wasn’t one of the main sub-companies, it was a sub-company from a sub-company. </p>
<p>To explain it better, if we name the 3 main sub-companies L, N, and P, then H was a sub-company of N.</p>
<p>Being a sub-sub-company didn’t mean the platform would be simpler to develop. It was quite the opposite, actually, given all the features proposed for the MVP.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/12/main_company_structure-1.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Main company structure</em></p>
<p>While the main goal was for a user to be able to purchase a product (seems quite obvious), there were too many dependencies with other services to accomplish this seemingly simple MVP.</p>
<p>Part of the product and order information came from another team’s domain, the Integrations team (I will call it team <em>In</em>). They communicated with <a target="_blank" href="https://www.swell.is/">Swell</a> and Klopotek, an ecommerce system where we stored the product's information along with the order’s status.</p>
<p>The discounts were also provided by team <em>In’s</em>, to which we had to subscribe and then calculate the final product price according to the user info and privileges before displaying it.</p>
<p>To make product content like images or descriptions accessible and customizable for the client we retrieved it through <a target="_blank" href="https://www.contentful.com/">Contentful</a>, a content platform where clients were able to manage it in an easy way.</p>
<p>We managed the payment with <a target="_blank" href="https://stripe.com/">Stripe</a>, a payments service, and then we communicated with team <em>In</em> to update the order status on Swell.</p>
<p>The service available for the user to authenticate should be agnostic to the owner and reusable on all sub-companies. It had to be provided by another team, yet in the end, we actually developed it ourselves.</p>
<p>And to put the icing on the cake, we also had to implement the user tracking with <a target="_blank" href="https://segment.com/">Segment</a>, a popular service to collect user events from web and mobile apps.</p>
<p>Here is a simple diagram of what I have been describing which might make it easier to understand. I have grouped the microservices architecture in just <em>Backend</em> and <em>Frontend</em> to keep it simple.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/12/mvp_architecture_overview-1.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>MVP Architecture overview</em></p>
<h2 id="heading-why-we-chose-graphql">Why We Chose GraphQL</h2>
<p>To accomplish our goals for the project, we had to <em>provide the frontend with a unique source of truth</em> of the product’s core information from the backend. </p>
<p>Therefore the only thing that we aimed to have different from one store’s frontend to another would be the designs and the content from Contentful. </p>
<p>Regarding these designs and their implementations on React, we planned to use a shared-components-library.</p>
<p>Therefore, what is GraphQL doing here and why did we decide to go for it? </p>
<p>Well, in case you don’t know how GraphQL works, essentially it lets you define a Schema with all the properties and queries that could be made to your product. Then it lets you serve it to the frontend to let it decide what to request without the backend having to create an endpoint for each of those requests (like in REST services). </p>
<p>To learn more about it, check out this tutorial <a target="_blank" href="https://www.ramonmorcillo.com/getting-started-with-graphql-and-nodejs/">I wrote to explain it</a>. It teaches you how to use it with Node.js. Also, <a target="_blank" href="https://graphql.org/learn/">their docs</a> are worth checking out.</p>
<p>This meant that each of the shops would request the data they needed from the product just by looking at the Schema, the source of truth. </p>
<p>Thanks to this fact we would not have to implement different sources of data  in the backend for each shop. This gave the frontend the power and responsibility (the first involves the second 🕷) to request the product data needed to display at each interface.</p>
<blockquote>
<p>With great power comes great responsibility.
— Stan Lee</p>
</blockquote>
<p>Just to be clear, if we had decided to go with REST we would have needed to create different endpoints for each of the shops. Or we would have had to make the frontend retrieve all the product data in each shop and then decide which properties to display. This means it would've had to store unnecessary data in the frontend that would only add noise. </p>
<p>Or even worse, we would have had all the shops’ backend services deployed for each one of the frontend shops. This would've used unnecessary resources and increased the cost considerably. </p>
<p>Here is why we took this initial approach. The worst part, in my opinion, would've been the waste of time from maintaining and hardly refactoring all the mess that we would have created.</p>
<p>Furthermore, by making a single request on-demand, the payload was lighter, and therefore, the performance over the network was improved.</p>
<p>Anyway, as with every problem, there were other approaches we could've taken on the way to developing this project and its architecture. But at that moment this one seemed to us the best one.</p>
<h2 id="heading-architecture-and-tech-stack">Architecture and Tech Stack</h2>
<p>The microservices architecture mainly consisted of Node.js services hosted on Azure K8s clusters. Depending on their needs and the data they worked with, they did or didn't have a MongoDB, PostgreSQL, or Redis database associated.</p>
<p>The asynchronous communication between them was handled mainly with <a target="_blank" href="https://azure.microsoft.com/en-us/services/service-bus/">Azure Service Bus</a> topics and subscriptions through a publish/subscribe messaging communication model. </p>
<p>The main difference with common messaging queues is that you can have more than one receiver, so you do not have multiple queues to receive messages in more than one service.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/12/azure_service_bus_messaging_queues-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Azure Service Bus messaging Queues. <a target="_blank" href="https://docs.microsoft.com/en-us/azure/service-bus-messaging/service-bus-messaging-overview#queues">Source</a></em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/12/azure_service_bus_messaging_topics-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Azure Service Bus messaging Topics. <a target="_blank" href="https://docs.microsoft.com/en-us/azure/service-bus-messaging/service-bus-messaging-overview#topics">Source</a></em></p>
<p>On the frontend part, the sites were developed with React. Sometimes we used <a target="_blank" href="https://github.com/vercel/next.js/">Next</a>, and other ones we built from scratch with <a target="_blank" href="https://github.com/facebook/create-react-app">Create React App</a>, depending on the complexity and the requirements of each. </p>
<p>We moved from Redux, used in previous projects, to the official <a target="_blank" href="https://reactjs.org/docs/context.html">Context API</a> to manage most of the state.</p>
<p>Here are the main services and their functionalities for the first MVP architecture: </p>
<ul>
<li><strong>shop-web-app:</strong> The client shop application.</li>
<li><strong>gateway-api-service:</strong> Proxy service to receive requests from the client and redirect them to the corresponding services.</li>
<li><strong>cms-api-service:</strong> Service to retrieve and serve the content from Contentful</li>
<li><strong>catalog-api-service:</strong> Service that subscribes to team In messages and persists the product core data to serve it later through GraphQL.</li>
<li><strong>orders-api-service.</strong> Service that handles all the payment business logic</li>
<li><strong>auth-api-service:</strong> Provisional service to implement the user authentication to be able to buy products.</li>
<li><strong>auth-web-app:</strong> The client for the auth service.</li>
<li><strong>integrations-ecommerce-api-service:</strong> service from the integrations domain that handles the payments. Although this service was not in our domain we developed it together to increase the delivery speed and free them from extra work.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/12/first_mvp_arquitecture-1.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>First MVP architecture</em></p>
<p>To deploy and update the resources needed on Azure we used <a target="_blank" href="https://www.terraform.io/">Terraform</a>, which let us define infrastructure as code and manage their life cycles on the K8s clusters. We also worked with Azure DevOps as our CI &amp; CD system.</p>
<p>On the services, we used <a target="_blank" href="https://github.com/guidesmiths/systemic">Systemic</a>, a Node.js framework for minimal dependency injection that lets you create components and their dependencies in a system. Each component handles a separate object from the domain such as the routing, controller, services, database, and so on in an agnostic way from the others.</p>
<p><a target="_blank" href="https://www.apollographql.com/">Apollo</a> was our choice to implement GraphQL. It provided us with a data graph layer to easily connect both frontend and backend. </p>
<p>Again, to learn more about it check out <a target="_blank" href="https://www.apollographql.com/docs/">their docs</a> or <a target="_blank" href="https://www.ramonmorcillo.com/getting-started-with-graphql-and-nodejs/">this tutorial.</a> </p>
<p>Finally, we hosted the code on <a target="_blank" href="https://github.com/">GitHub</a> to make use of features like Pull Requests to review our code properly before implementing it.</p>
<h2 id="heading-the-second-mvp">The second MVP</h2>
<p>An MVP (Minimum Viable Product) is the first prototype you create and deliver in a project. This means that there is usually just one, and when you create it you start implementing new features on it. </p>
<p>So, why did we focus on a second MVP for the same project? Well, when we reached a “stable” version of the first one, the client realized that we needed to start with the main sub-company stores. They decided to stop the sub-sub-company H store development to focus on the development of the new ones. </p>
<p>This was mainly because to some services ended their support for the sub-companies in the coming months, meaning that their stores had to be developed first.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/12/how_we_felt_with_second_mvp-1.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Graphical representation of how we felt with the second MVP</em></p>
<p>Although we tried to make a proper estimation for the first MVP, we surpassed its deadline since some unplanned issues appeared along the way. Thus, when we were told that the new deadline would be even sooner, we decided to take a different approach to reach it on time. </p>
<p>We decided to develop more than one store at the same time, which was a double-edged sword approach. </p>
<p>On one hand, we would see on the go how well the reusability aspect of our platform worked while refactoring it. We would also end up with more than one store in the end. </p>
<p>On the other hand, we would have to set up and maintain the environments and resources of multiple shops. Plus we would have to implement their designs which would slow us down, meaning we might not reach the deadline on time, again.</p>
<p>We saw this MVP as an opportunity to start over and improve our codebase. So we added TypesScript and Styled-Components to our React application. </p>
<p>I have to admit that I was very happy when we made these choices because I had been working with that stack on <a target="_blank" href="https://github.com/reymon359?tab=repositories&amp;q=&amp;type=source&amp;language=typescript">my own projects</a>. So now I was able to learn more and get even better at it.</p>
<p>Fortunateluy, we were able to reuse most of the code from the previous MVP for the React apps and the backend services. But not everything was a bed of roses. </p>
<p>Not all of us were used to working with this new stack and it slowed us down at the beginning. Furthermore, with the same stack, we started developing a React components library for all the platforms, which, even though it was planned for the first MVP, never saw the light.</p>
<p>By that time, the team in charge of the user authentication service started working on it so we stopped its development and just implemented it on the site. </p>
<p>In addition, we started the development of a products search service (<strong>search-api-service</strong>) with <a target="_blank" href="https://azure.microsoft.com/en-us/services/search/">Azure Cognitive Search</a>.</p>
<p>After all the changes mentioned above the architecture evolved this way.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/12/second_mvp_arquitecture.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Second MVP architecture</em></p>
<h2 id="heading-conclusion-and-lessons-learned">Conclusion and lessons learned</h2>
<p>As I am writing this, the platform isn’t finished yet. But it has been a great challenge to get where we are. </p>
<p>We have learned some valuable lessons that can be useful to others, not just about the stack and architecture described above but about the way we worked as a team.</p>
<h3 id="heading-innovate-the-stack">Innovate the stack</h3>
<p>Working with new technologies can be risky and less comfortable than sticking with old and well-known ones. But innovation and adaptability is the right way to go so you don't get left behind in Software Development. </p>
<p>One of the most important points when you upgrade your stack or adopt a new one, apart from checking the proper way to do so following standards, is <em>being sure the team is comfortable working with it,</em>. Not just at the beginning, either, but during the whole process to make the transition easier.</p>
<h3 id="heading-dont-underestimate-promise-less-deliver-more">Don’t underestimate, promise less, deliver more</h3>
<p>We happily estimated the first MVP and agreed to deliver a great number of features. We ended up needing more time because of all the issues that appeared on the way and _had to learn to say “no” <em>sometimes.</em> </p>
<p>On the second MVP, we didn’t estimate that far ahead in time and didn’t commit ourselves to features we weren’t sure we could deliver within the time expected. </p>
<p>Because of this, we were able to work less stressed, have a better mood, deliver better code, and improve the client's feelings about the project since they weren’t disappointed with the progress.</p>
<h3 id="heading-teamwork-inside-the-team">Teamwork inside the team.</h3>
<p>We realized that the best way to progress and develop was to feel comfortable – not just with the technologies but, most importantly, our teammates. Some of the measures that improved our relationship and teamwork were:</p>
<h4 id="heading-team-democracy">Team democracy.</h4>
<p>No matter the work we were doing at the moment, <em>all of us had the same voice and our opinion counted the same</em> when making a choice. This was key when we discussed the adoption of the new stack and the practices we would follow.</p>
<h4 id="heading-reviewing-code">Reviewing code.</h4>
<p>Feedback is one of the best ways to improve not only the code itself but the way you write it too. That's why we decided to work with GitHub Pull Requests to implement most of the features. </p>
<p><em>Working with them not only improved our code base but also made us aware of how the features were being implemented in other areas, avoiding catchup meetings and helping us keep track of the full project scope</em>. </p>
<p>We refined this system little by little with features like a <a target="_blank" href="https://docs.github.com/en/free-pro-team@latest/github/administering-a-repository/about-required-reviews-for-pull-requests">minimum number of reviewers to merge them</a> or <a target="_blank" href="https://github.com/integrations/slack">subscribing to them through slack.</a></p>
<h4 id="heading-helping-and-asking-for-help">Helping and asking for help.</h4>
<p>In my opinion, this one is a must. <em>The team must lose the fear of asking for help if they get stuck. At the same time, they must be willing to help others when they ask for it.</em> </p>
<p>I am happy to say that we were able to reach this balance and our work improved in many ways. The next point, pairing, was key in losing the fear of asking for help and getting to know each other better.</p>
<h4 id="heading-pairing-as-much-as-possible">Pairing as much as possible.</h4>
<p>At this point in software development, the advantages of doing pair programming are quite well known. We paired not just to deliver the features in a faster and better way of doing things, but to learn from each other's way of coding. </p>
<p>Each week, we decided the pairing tasks and teammates to implement them. But if someone needed or wanted to pair, we just asked for it and moments after a teammate offered to help.</p>
<h4 id="heading-paying-attention-to-feedback">Paying attention to feedback.</h4>
<p>The sprint retrospectives were the perfect moment to review all the things that went well, those that went wrong, to propose changes, and to look forward to improvement. Therefore the more we shared our opinions the more issues we could approach and solve.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/12/teamwork_makes_the_dream_work.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<h4 id="heading-teamwork-with-other-partners">Teamwork with other partners.</h4>
<p>We were dependent on other teams' work – so having a good relationship with them was also an important point in our development process. </p>
<p><em>Communication was the key point: the more we communicated the more we improved,</em>. And thanks to this, our goal was to be one whole team. Here are some actions we followed in order to enhance this communication:</p>
<ul>
<li><strong>Have a private place just for us.</strong> We created a separate channel to talk about the progress and solve any questions or doubts as soon as possible without extra meetings.</li>
<li><strong>Quick meetings.</strong> A meeting once a week worked great to check the progress on the main issues. But we did not always wait for this one meeting, and had a quick call whenever an issue needed to be discussed.</li>
<li><strong>Stay updated on the overall progress.</strong> We had a teammate from our team attending their daily standups and one of them at ours who updated the rest of the team if needed.</li>
</ul>
<p>Here is some actual footage of us and the Integrations Team:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/12/source--1-.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<h4 id="heading-make-the-client-feel-like-part-of-the-team">Make the client feel like part of the team.</h4>
<p>At the beginning of the first MVP, there were too many clues and too little communication to clarify them so we were blocked sometimes or had to set up time-wasting meetings for these issues. </p>
<p>The core of the problem, like most problems in life, was a lack of communication. So we solved it by increasing our communication, asking questions directly to the client, inviting them to retrospectives, daily standups, and other meetings even when they were not required.</p>
<p>This helped keep the client updated as much as possible. In the end, the more we communicated the more we made them feel part of the team, and the better we worked together.</p>
<h2 id="heading-final-thoughts">Final thoughts</h2>
<p>I want to first thank my teammates. It has been a pleasure to work with them, starting each day eager to have fun together developing the project.</p>
<p>On the same level, thank you to the teammates from other teams who always gave a helping hand when requested.</p>
<p>I'm also thankful for the opportunity to participate in the full end-to-end implementation of the project from which I learned so much. I solved issues on Front, Back, and DevOps such as setting up environments, pipelines, messaging between services, persisting and retrieving data, serving it to the frontend, and implementing the interfaces to display it.</p>
<p>Finally, I am thankful for having the chance to work and get better at technologies that I was using on side-projects like GraphQL or TypeScript.</p>
<p>I hope you enjoyed this article. You can read <a target="_blank" href="https://ramonmorcillo.com/developing-a-reusable-ecommerce-platform/">it too on my site</a> along with others! If you've got any questions, suggestions, or feedback in general, don't hesitate to reach out on any of the social networks from <a target="_blank" href="https://ramonmorcillo.com/">my site</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Develop and Deploy Micro-Frontends with Single-SPA ]]>
                </title>
                <description>
                    <![CDATA[ By Tyler Hawkins Micro-frontends are the future of front end web development. Inspired by microservices, which allow you to break up your backend into smaller pieces, micro-frontends allow you to build, test, and deploy pieces of your frontend app in... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/developing-and-deploying-micro-frontends-with-single-spa/</link>
                <guid isPermaLink="false">66d4617438f2dc3808b79113</guid>
                
                    <category>
                        <![CDATA[ architecture ]]>
                    </category>
                
                    <category>
                        <![CDATA[ AWS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Front-end Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Heroku ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Travis CI ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Mon, 03 Aug 2020 11:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/07/single-spa-3.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Tyler Hawkins</p>
<p>Micro-frontends are the future of front end web development.</p>
<p>Inspired by microservices, which allow you to break up your backend into smaller pieces, micro-frontends allow you to build, test, and deploy pieces of your frontend app independently of each other. </p>
<p>Depending on the micro-frontend framework you choose, you can even have multiple micro-frontend apps — written in React, Angular, Vue, or anything else — coexisting peacefully together in the same larger app.</p>
<p>In this article, we’re going to develop an app composed of micro-frontends using <a target="_blank" href="https://single-spa.js.org/">single-spa</a> and deploy it to <a target="_blank" href="https://www.heroku.com/">Heroku</a>. </p>
<p>We’ll set up continuous integration using <a target="_blank" href="https://travis-ci.org/">Travis CI</a>. Each CI pipeline will bundle the JavaScript for a micro-frontend app and then upload the resulting build artifacts to <a target="_blank" href="https://aws.amazon.com/s3/">AWS S3</a>. </p>
<p>Finally, we’ll make an update to one of the micro-frontend apps and see how it can be deployed to production independently of the other micro-frontend apps.</p>
<h1 id="heading-overview-of-the-demo-app">Overview of the Demo App</h1>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/07/mfe1.png" alt="Demo app — end result" width="600" height="400" loading="lazy">
<em>Demo app — end result</em></p>
<p>Before we discuss the step-by-step instructions, let’s get a quick overview of what makes up the demo app. This app is composed of four sub-apps:</p>
<ol>
<li>A <a target="_blank" href="https://github.com/thawkin3/single-spa-demo-root-config">container app</a> that serves as the main page container and coordinates the mounting and unmounting of the micro-frontend apps</li>
<li>A <a target="_blank" href="https://github.com/thawkin3/single-spa-demo-nav">micro-frontend navbar app</a> that’s always present on the page</li>
<li>A <a target="_blank" href="https://github.com/thawkin3/single-spa-demo-page-1">micro-frontend “page 1” app</a> that only shows when active</li>
<li>A <a target="_blank" href="https://github.com/thawkin3/single-spa-demo-page-2">micro-frontend “page 2” app</a> that also only shows when active</li>
</ol>
<p>These four apps all live in separate repos, available on GitHub, which I’ve linked to above.</p>
<p>The end result is fairly simple in terms of the user interface, but, to be clear, the user interface isn’t the point here. </p>
<p>If you’re following along on your own machine, by the end of this article you too will have all the underlying infrastructure necessary to get started with your own micro-frontend app.</p>
<p>Alright, grab your scuba gear, because it’s time to dive in!</p>
<h1 id="heading-creating-the-container-app">Creating the Container App</h1>
<p>To generate the apps for this demo, we’re going to use a command-line interface (CLI) tool called <a target="_blank" href="https://single-spa.js.org/docs/create-single-spa/">create-single-spa</a>. The version of create-single-spa at the time of writing is 1.10.0, and the version of single-spa installed via the CLI is 4.4.2.</p>
<p>We’ll follow these steps to create the container app (also sometimes called the root config):</p>
<pre><code class="lang-bash">mkdir single-spa-demo

<span class="hljs-built_in">cd</span> single-spa-demo

mkdir single-spa-demo-root-config

<span class="hljs-built_in">cd</span> single-spa-demo-root-config

npx create-single-spa
</code></pre>
<p>We’ll then follow the CLI prompts:</p>
<ol>
<li>Select “single spa root config”</li>
<li>Select “yarn” or “npm” (I chose “yarn”)</li>
<li>Enter an organization name (I used “thawkin3,” but it can be whatever you want)</li>
</ol>
<p>Great! Now, if you check out the <code>single-spa-demo-root-config</code> directory, you should see a skeleton root config app. We'll customize this in a bit, but first let's also use the CLI tool to create our other three micro-frontend apps.</p>
<h1 id="heading-creating-the-micro-frontend-apps">Creating the Micro-Frontend Apps</h1>
<p>To generate our first micro-frontend app, the navbar, we’ll follow these steps:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> ..

mkdir single-spa-demo-nav

<span class="hljs-built_in">cd</span> single-spa-demo-nav

npx create-single-spa
</code></pre>
<p>We’ll then follow the CLI prompts:</p>
<ol>
<li>Select “single-spa application / parcel”</li>
<li>Select “react”</li>
<li>Select “yarn” or “npm” (I chose “yarn”)</li>
<li>Enter an organization name, the same one you used when creating the root config app (“thawkin3” in my case)</li>
<li>Enter a project name (I used “single-spa-demo-nav”)</li>
</ol>
<p>Now that we’ve created the navbar app, we can follow these same steps to create our two page apps. But, we’ll replace each place we see “single-spa-demo-nav” with “single-spa-demo-page-1” the first time through and then with “single-spa-demo-page-2” the second time through.</p>
<p>At this point we’ve generated all four apps that we need: one container app and three micro-frontend apps. Now it’s time to hook our apps together.</p>
<h1 id="heading-registering-the-micro-frontend-apps-with-the-container-app">Registering the Micro-Frontend Apps with the Container App</h1>
<p>As stated before, one of the container app’s primary responsibilities is to coordinate when each app is “active” or not. In other words, it handles when each app should be shown or hidden. </p>
<p>To help the container app understand when each app should be shown, we provide it with what are called “activity functions.” Each app has an activity function that simply returns a boolean, true or false, for whether or not the app is currently active.</p>
<p>Inside the <code>single-spa-demo-root-config</code> directory, in the <code>activity-functions.js</code> file, we'll write the following activity functions for our three micro-frontend apps.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">prefix</span>(<span class="hljs-params">location, ...prefixes</span>) </span>{
  <span class="hljs-keyword">return</span> prefixes.some(
    <span class="hljs-function"><span class="hljs-params">prefix</span> =&gt;</span> location.href.indexOf(<span class="hljs-string">`<span class="hljs-subst">${location.origin}</span>/<span class="hljs-subst">${prefix}</span>`</span>) !== <span class="hljs-number">-1</span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">nav</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// The nav is always active</span>
  <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
}

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">page1</span>(<span class="hljs-params">location</span>) </span>{
  <span class="hljs-keyword">return</span> prefix(location, <span class="hljs-string">'page1'</span>);
}

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">page2</span>(<span class="hljs-params">location</span>) </span>{
  <span class="hljs-keyword">return</span> prefix(location, <span class="hljs-string">'page2'</span>);
}
</code></pre>
<p>Next, we need to register our three micro-frontend apps with single-spa. To do that, we use the <code>registerApplication</code> function. This function accepts a minimum of three arguments: the app name, a method to load the app, and an activity function to determine when the app is active.</p>
<p>Inside the <code>single-spa-demo-root-config</code> directory, in the <code>root-config.js</code> file, we'll add the following code to register our apps:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { registerApplication, start } <span class="hljs-keyword">from</span> <span class="hljs-string">"single-spa"</span>;
<span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> isActive <span class="hljs-keyword">from</span> <span class="hljs-string">"./activity-functions"</span>;

registerApplication(
  <span class="hljs-string">"@thawkin3/single-spa-demo-nav"</span>,
  <span class="hljs-function">() =&gt;</span> System.import(<span class="hljs-string">"@thawkin3/single-spa-demo-nav"</span>),
  isActive.nav
);

registerApplication(
  <span class="hljs-string">"@thawkin3/single-spa-demo-page-1"</span>,
  <span class="hljs-function">() =&gt;</span> System.import(<span class="hljs-string">"@thawkin3/single-spa-demo-page-1"</span>),
  isActive.page1
);

registerApplication(
  <span class="hljs-string">"@thawkin3/single-spa-demo-page-2"</span>,
  <span class="hljs-function">() =&gt;</span> System.import(<span class="hljs-string">"@thawkin3/single-spa-demo-page-2"</span>),
  isActive.page2
);

start();
</code></pre>
<p>Now that we’ve set up the activity functions and registered our apps, the last step before we can get this running locally is to update the local import map inside the <code>index.ejs</code> file in the same directory. </p>
<p>We'll add the following code inside the <code>head</code> tag to specify where each app can be found when running locally:</p>
<pre><code class="lang-javascript">&lt;% <span class="hljs-keyword">if</span> (isLocal) { %&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"systemjs-importmap"</span>&gt;</span><span class="javascript">
    {
      <span class="hljs-string">"imports"</span>: {
        <span class="hljs-string">"@thawkin3/root-config"</span>: <span class="hljs-string">"http://localhost:9000/root-config.js"</span>,
        <span class="hljs-string">"@thawkin3/single-spa-demo-nav"</span>: <span class="hljs-string">"http://localhost:9001/thawkin3-single-spa-demo-nav.js"</span>,
        <span class="hljs-string">"@thawkin3/single-spa-demo-page-1"</span>: <span class="hljs-string">"http://localhost:9002/thawkin3-single-spa-demo-page-1.js"</span>,
        <span class="hljs-string">"@thawkin3/single-spa-demo-page-2"</span>: <span class="hljs-string">"http://localhost:9003/thawkin3-single-spa-demo-page-2.js"</span>
      }
    }
  </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span></span>
&lt;% } %&gt;
</code></pre>
<p>Each app contains its own startup script, which means that each app will be running locally on its own development server during local development. As you can see, our navbar app is on port 9001, our page 1 app is on port 9002, and our page 2 app is on port 9003.</p>
<p>With those three steps taken care of, let’s try out our app.</p>
<h1 id="heading-test-run-for-running-locally">Test Run for Running Locally</h1>
<p>To get our app running locally, we can follow these steps:</p>
<ol>
<li>Open four terminal tabs, one for each app</li>
<li>For the root config, in the <code>single-spa-demo-root-config</code> directory: <code>yarn start</code> (runs on port 9000 by default)</li>
<li>For the nav app, in the <code>single-spa-demo-nav</code> directory: <code>yarn start --port 9001</code></li>
<li>For the page 1 app, in the <code>single-spa-demo-page-1</code> directory: <code>yarn start --port 9002</code></li>
<li>For the page 2 app, in the <code>single-spa-demo-page-2</code> directory: <code>yarn start --port 9003</code></li>
</ol>
<p>Now, we’ll navigate in the browser to <a target="_blank" href="http://localhost:9000/">http://localhost:9000</a> to view our app.</p>
<p>We should see… some text! Super exciting.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/07/mfe2.png" alt="Demo app — main page" width="600" height="400" loading="lazy">
<em>Demo app — main page</em></p>
<p>On our main page, the navbar is showing because the navbar app is always active.</p>
<p>Now, let’s navigate to <a target="_blank" href="http://localhost:9000/page1.">http://localhost:9000/page1.</a> As shown in our activity functions above, we’ve specified that the page 1 app should be active (shown) when the URL path begins with “page1.” So, this activates the page 1 app, and we should see the text for both the navbar and the page 1 app now.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/07/mfe3.png" alt="Demo app — page 1 route" width="600" height="400" loading="lazy">
<em>Demo app — page 1 route</em></p>
<p>One more time, let’s now navigate to <a target="_blank" href="http://localhost:9000/page2.">http://localhost:9000/page2.</a> As expected, this activates the page 2 app, so we should see the text for the navbar and the page 2 app now.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/07/mfe4.png" alt="Demo app — page 2 route" width="600" height="400" loading="lazy">
<em>Demo app — page 2 route</em></p>
<h1 id="heading-making-minor-tweaks-to-the-apps">Making Minor Tweaks to the Apps</h1>
<p>So far our app isn’t very exciting to look at, but we do have a working micro-frontend setup running locally. If you aren’t cheering in your seat right now, you should be!</p>
<p>Let’s make some minor improvements to our apps so they look and behave a little nicer.</p>
<h3 id="heading-specifying-the-mount-containers">Specifying the Mount Containers</h3>
<p>First, if you refresh your page over and over when viewing the app, you may notice that sometimes the apps load out of order, with the page app appearing above the navbar app. </p>
<p>This is because we haven’t actually specified <em>where</em> each app should be mounted. The apps are simply loaded by <a target="_blank" href="https://github.com/systemjs/systemjs">SystemJS</a>, and then whichever app finishes loading fastest gets appended to the page first.</p>
<p>We can fix this by specifying a mount container for each app when we register them.</p>
<p>In our <code>index.ejs</code> file that we worked in previously, let's add some HTML to serve as the main content containers for the page:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"nav-container"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">main</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"page-1-container"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"page-2-container"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span>
</code></pre>
<p>Then, in our <code>root-config.js</code> file where we've registered our apps, let's provide a fourth argument to each function call that includes the DOM element where we'd like to mount each app:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { registerApplication, start } <span class="hljs-keyword">from</span> <span class="hljs-string">"single-spa"</span>;
<span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> isActive <span class="hljs-keyword">from</span> <span class="hljs-string">"./activity-functions"</span>;

registerApplication(
  <span class="hljs-string">"@thawkin3/single-spa-demo-nav"</span>,
  <span class="hljs-function">() =&gt;</span> System.import(<span class="hljs-string">"@thawkin3/single-spa-demo-nav"</span>),
  isActive.nav,
  { <span class="hljs-attr">domElement</span>: <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'nav-container'</span>) }
);

registerApplication(
  <span class="hljs-string">"@thawkin3/single-spa-demo-page-1"</span>,
  <span class="hljs-function">() =&gt;</span> System.import(<span class="hljs-string">"@thawkin3/single-spa-demo-page-1"</span>),
  isActive.page1,
  { <span class="hljs-attr">domElement</span>: <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'page-1-container'</span>) }
);

registerApplication(
  <span class="hljs-string">"@thawkin3/single-spa-demo-page-2"</span>,
  <span class="hljs-function">() =&gt;</span> System.import(<span class="hljs-string">"@thawkin3/single-spa-demo-page-2"</span>),
  isActive.page2,
  { <span class="hljs-attr">domElement</span>: <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'page-2-container'</span>) }
);

start();
</code></pre>
<p>Now, the apps will always be mounted to a specific and predictable location. Nice!</p>
<h3 id="heading-styling-the-app">Styling the App</h3>
<p>Next, let’s style up our app a bit. Plain black text on a white background isn’t very interesting to look at.</p>
<p>In the <code>single-spa-demo-root-config</code> directory, in the <code>index.ejs</code> file again, we can add some basic styles for the whole app by pasting the following CSS at the bottom of the <code>head</code> tag:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css">
  <span class="hljs-selector-tag">body</span>, <span class="hljs-selector-tag">html</span> { <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>; <span class="hljs-attribute">padding</span>: <span class="hljs-number">0</span>; <span class="hljs-attribute">font-size</span>: <span class="hljs-number">16px</span>; <span class="hljs-attribute">font-family</span>: Arial, Helvetica, sans-serif; <span class="hljs-attribute">height</span>: <span class="hljs-number">100%</span>; }
  <span class="hljs-selector-tag">body</span> { <span class="hljs-attribute">display</span>: flex; <span class="hljs-attribute">flex-direction</span>: column; }
  * { <span class="hljs-attribute">box-sizing</span>: border-box; }
</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>
</code></pre>
<p>Next, we can style our navbar app by finding the <code>single-spa-demo-nav</code> directory, creating a <code>root.component.css</code> file, and adding the following CSS:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.nav</span> {
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">flex-direction</span>: row;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">20px</span>;
  <span class="hljs-attribute">background</span>: <span class="hljs-number">#000</span>;
  <span class="hljs-attribute">color</span>: <span class="hljs-number">#fff</span>;
}

<span class="hljs-selector-class">.link</span> {
  <span class="hljs-attribute">margin-right</span>: <span class="hljs-number">20px</span>;
  <span class="hljs-attribute">color</span>: <span class="hljs-number">#fff</span>;
  <span class="hljs-attribute">text-decoration</span>: none;
}

<span class="hljs-selector-class">.link</span><span class="hljs-selector-pseudo">:hover</span>,
<span class="hljs-selector-class">.link</span><span class="hljs-selector-pseudo">:focus</span> {
  <span class="hljs-attribute">color</span>: <span class="hljs-number">#1098f7</span>;
}
</code></pre>
<p>We can then update the <code>root.component.js</code> file in the same directory to import the CSS file and apply those classes and styles to our HTML. We'll also change the navbar content to actually contain two links so we can navigate around the app by clicking the links instead of entering a new URL in the browser's address bar.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"./root.component.css"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Root</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">nav</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"nav"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/page1"</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"link"</span>&gt;</span>
        Page 1
      <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/page2"</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"link"</span>&gt;</span>
        Page 2
      <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">nav</span>&gt;</span></span>
  );
}
</code></pre>
<p>We’ll follow a similar process for the page 1 and page 2 apps as well. We’ll create a <code>root.component.css</code> file for each app in their respective project directories and update the <code>root.component.js</code> files for both apps too.</p>
<p>For the page 1 app, the changes look like this:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.container1</span> {
  <span class="hljs-attribute">background</span>: <span class="hljs-number">#1098f7</span>;
  <span class="hljs-attribute">color</span>: white;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">20px</span>;
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">align-items</span>: center;
  <span class="hljs-attribute">justify-content</span>: center;
  <span class="hljs-attribute">flex</span>: <span class="hljs-number">1</span>;
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">3rem</span>;
}
</code></pre>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"./root.component.css"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Root</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"container1"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Page 1 App<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>And for the page 2 app, the changes look like this:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.container2</span> {
  <span class="hljs-attribute">background</span>: <span class="hljs-number">#9e4770</span>;
  <span class="hljs-attribute">color</span>: white;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">20px</span>;
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">align-items</span>: center;
  <span class="hljs-attribute">justify-content</span>: center;
  <span class="hljs-attribute">flex</span>: <span class="hljs-number">1</span>;
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">3rem</span>;
}
</code></pre>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"./root.component.css"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Root</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"container2"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Page 2 App<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<h3 id="heading-adding-react-router">Adding React Router</h3>
<p>The last small change we’ll make is to add <a target="_blank" href="https://reacttraining.com/react-router/">React Router</a> to our app. Right now the two links we’ve placed in the navbar are just normal anchor tags, so navigating from page to page causes a page refresh. Our app will feel much smoother if the navigation is handled client-side with React Router.</p>
<p>To use React Router, we’ll first need to install it. From the terminal, in the <code>single-spa-demo-nav</code> directory, we'll install React Router using yarn by entering <code>yarn add react-router-dom</code>. (Or if you're using npm, you can enter <code>npm install react-router-dom</code>.)</p>
<p>Then, in the <code>single-spa-demo-nav</code> directory in the <code>root.component.js</code> file, we'll replace our anchor tags with React Router's <code>Link</code> components like so:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { BrowserRouter, Link } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-router-dom"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"./root.component.css"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Root</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">BrowserRouter</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">nav</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"nav"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"/page1"</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"link"</span>&gt;</span>
          Page 1
        <span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"/page2"</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"link"</span>&gt;</span>
          Page 2
        <span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">nav</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">BrowserRouter</span>&gt;</span></span>
  );
}
</code></pre>
<p>Cool. That looks and works much better!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/07/mfe5.png" alt="Demo app — styled and using React Router" width="600" height="400" loading="lazy">
<em>Demo app — styled and using React Router</em></p>
<h1 id="heading-getting-ready-for-production">Getting Ready for Production</h1>
<p>At this point we have everything we need to continue working on the app while running it locally. But how do we get it hosted somewhere publicly available? </p>
<p>There are several possible approaches we can take using our tools of choice, but the main tasks are:</p>
<ol>
<li>to have somewhere we can upload our build artifacts, like a CDN, and</li>
<li>to automate this process of uploading artifacts each time we merge new code into the master branch.</li>
</ol>
<p>For this article, we’re going to use AWS S3 to store our assets, and we’re going to use Travis CI to run a build job and an upload job as part of a continuous integration pipeline.</p>
<p>Let’s get the S3 bucket set up first.</p>
<h3 id="heading-setting-up-the-aws-s3-bucket">Setting up the AWS S3 Bucket</h3>
<p>It should go without saying, but you’ll need an AWS account if you’re following along here. </p>
<p>If we are the root user on our AWS account, we can create a new IAM user that has programmatic access only. This means we’ll be given an access key ID and a secret access key from AWS when we create the new user. We’ll want to store these in a safe place since we’ll need them later. </p>
<p>Finally, this user should be given permissions to work with S3 only, so that the level of access is limited if our keys were to fall into the wrong hands.</p>
<p>AWS has some great resources for <a target="_blank" href="https://docs.aws.amazon.com/general/latest/gr/aws-access-keys-best-practices.html">best practices with access keys</a> and <a target="_blank" href="https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html">managing access keys for IAM users</a> that would be well worth checking out if you’re unfamiliar with how to do this.</p>
<p>Next we need to create an S3 bucket. S3 stands for Simple Storage Service and is essentially a place to upload and store files hosted on Amazon’s servers. A bucket is simply a directory. </p>
<p>I’ve named my bucket “single-spa-demo,” but you can name yours whatever you’d like. You can follow the AWS guides for <a target="_blank" href="https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingBucket.html">how to create a new bucket</a> for more info.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/07/mfe6.png" alt="AWS S3 bucket" width="600" height="400" loading="lazy">
<em>AWS S3 bucket</em></p>
<p>Once we have our bucket created, it’s also important to make sure the bucket is public and that <a target="_blank" href="https://docs.aws.amazon.com/AmazonS3/latest/dev/cors.html#how-do-i-enable-cors">CORS (cross-origin resource sharing) is enabled for our bucket</a> so that we can access and use our uploaded assets in our app. </p>
<p>In the permissions for our bucket, we can add the following CORS configuration rules:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">CORSConfiguration</span>&gt;</span>
 <span class="hljs-tag">&lt;<span class="hljs-name">CORSRule</span>&gt;</span>
   <span class="hljs-tag">&lt;<span class="hljs-name">AllowedOrigin</span>&gt;</span>*<span class="hljs-tag">&lt;/<span class="hljs-name">AllowedOrigin</span>&gt;</span>
   <span class="hljs-tag">&lt;<span class="hljs-name">AllowedMethod</span>&gt;</span>GET<span class="hljs-tag">&lt;/<span class="hljs-name">AllowedMethod</span>&gt;</span>
 <span class="hljs-tag">&lt;/<span class="hljs-name">CORSRule</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">CORSConfiguration</span>&gt;</span>
</code></pre>
<p>In the AWS console, it ends up looking like this after we hit Save:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/07/mfe7.png" alt="Image" width="600" height="400" loading="lazy">
<em>CORS configuration</em></p>
<h3 id="heading-creating-a-travis-ci-job-to-upload-artifacts-to-aws-s3">Creating a Travis CI Job to Upload Artifacts to AWS S3</h3>
<p>Now that we have somewhere to upload files, let’s set up an automated process that will take care of uploading new JavaScript bundles each time we merge new code into the master branch for any of our repos.</p>
<p>To do this, we’re going to use <a target="_blank" href="https://travis-ci.org/">Travis CI</a>. As mentioned earlier, each app lives in its own repo on GitHub, so we have four GitHub repos to work with. We can <a target="_blank" href="https://docs.travis-ci.com/user/tutorial/#to-get-started-with-travis-ci-using-github">integrate Travis CI with each of our repos</a> and set up continuous integration pipelines for each one.</p>
<p>To configure Travis CI for any given project, we create a <code>.travis.yml</code> file in the project's root directory. Let's create that file in the <code>single-spa-demo-root-config</code> directory and insert the following code:</p>
<pre><code class="lang-yaml"><span class="hljs-attr">language:</span> <span class="hljs-string">node_js</span>
<span class="hljs-attr">node_js:</span>
  <span class="hljs-bullet">-</span> <span class="hljs-string">node</span>
<span class="hljs-attr">script:</span>
  <span class="hljs-bullet">-</span> <span class="hljs-string">yarn</span> <span class="hljs-string">build</span>
  <span class="hljs-bullet">-</span> <span class="hljs-string">echo</span> <span class="hljs-string">"Commit sha - $TRAVIS_COMMIT"</span>
  <span class="hljs-bullet">-</span> <span class="hljs-string">mkdir</span> <span class="hljs-string">-p</span> <span class="hljs-string">dist/@thawkin3/root-config/$TRAVIS_COMMIT</span>
  <span class="hljs-bullet">-</span> <span class="hljs-string">mv</span> <span class="hljs-string">dist/*.*</span> <span class="hljs-string">dist/@thawkin3/root-config/$TRAVIS_COMMIT/</span>
<span class="hljs-attr">deploy:</span>
  <span class="hljs-attr">provider:</span> <span class="hljs-string">s3</span>
  <span class="hljs-attr">access_key_id:</span> <span class="hljs-string">"$AWS_ACCESS_KEY_ID"</span>
  <span class="hljs-attr">secret_access_key:</span> <span class="hljs-string">"$AWS_SECRET_ACCESS_KEY"</span>
  <span class="hljs-attr">bucket:</span> <span class="hljs-string">"single-spa-demo"</span>
  <span class="hljs-attr">region:</span> <span class="hljs-string">"us-west-2"</span>
  <span class="hljs-attr">cache-control:</span> <span class="hljs-string">"max-age=31536000"</span>
  <span class="hljs-attr">acl:</span> <span class="hljs-string">"public_read"</span>
  <span class="hljs-attr">local_dir:</span> <span class="hljs-string">dist</span>
  <span class="hljs-attr">skip_cleanup:</span> <span class="hljs-literal">true</span>
  <span class="hljs-attr">on:</span>
    <span class="hljs-attr">branch:</span> <span class="hljs-string">master</span>
</code></pre>
<p>This implementation is what I came up with after reviewing the <a target="_blank" href="https://docs.travis-ci.com/user/deployment-v2/providers/s3/">Travis CI docs for AWS S3 uploads</a> and a <a target="_blank" href="https://github.com/single-spa/import-map-deployer/blob/master/examples/ci-for-javascript-repo/travis-digital-ocean-spaces/.travis.yml">single-spa Travis CI example config</a>.</p>
<p>Because we don’t want our AWS secrets exposed in our GitHub repo, we can store those as environment variables. You can place environment variables and their secret values within the Travis CI web console for anything that you want to keep private, so that’s where the <code>.travis.yml</code> file gets those values from.</p>
<p>Now, when we commit and push new code to the master branch, the Travis CI job will run, which will build the JavaScript bundle for the app and then upload those assets to S3. To verify, we can check out the AWS console to see our newly uploaded files:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/07/mfe8.png" alt="Uploaded files as a result of a Travis CI job" width="600" height="400" loading="lazy">
<em>Uploaded files as a result of a Travis CI job</em></p>
<p>Neat! So far so good. Now we need to implement the same Travis CI configuration for our other three micro-frontend apps, but swapping out the directory names in the <code>.travis.yml</code> file as needed. After following the same steps and merging our code, we now have four directories created in our S3 bucket, one for each repo.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/07/mfe9.png" alt="Four directories within our S3 bucket" width="600" height="400" loading="lazy">
<em>Four directories within our S3 bucket</em></p>
<h1 id="heading-creating-an-import-map-for-production">Creating an Import Map for Production</h1>
<p>Let’s recap what we’ve done so far. We have four apps, all living in separate GitHub repos. Each repo is set up with Travis CI to run a job when code is merged into the master branch, and that job handles uploading the build artifacts into an S3 bucket. </p>
<p>With all that in one place, there’s still one thing missing: How do these new build artifacts get referenced in our container app? In other words, even though we’re pushing up new JavaScript bundles for our micro-frontends with each new update, the new code isn’t actually used in our container app yet!</p>
<p>If we think back to how we got our app running locally, we used an import map. This import map is simply JSON that tells the container app where each JavaScript bundle can be found. </p>
<p>But, our import map from earlier was specifically used for running the app locally. Now we need to create an import map that will be used in the production environment.</p>
<p>If we look in the <code>single-spa-demo-root-config</code> directory, in the <code>index.ejs</code> file, we see this line:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"systemjs-importmap"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://storage.googleapis.com/react.microfrontends.app/importmap.json"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<p>Opening up that URL in the browser reveals an import map that looks like this:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"imports"</span>: {
    <span class="hljs-attr">"react"</span>: <span class="hljs-string">"https://cdn.jsdelivr.net/npm/react@16.13.1/umd/react.production.min.js"</span>,
    <span class="hljs-attr">"react-dom"</span>: <span class="hljs-string">"https://cdn.jsdelivr.net/npm/react-dom@16.13.1/umd/react-dom.production.min.js"</span>,
    <span class="hljs-attr">"single-spa"</span>: <span class="hljs-string">"https://cdn.jsdelivr.net/npm/single-spa@5.5.3/lib/system/single-spa.min.js"</span>,
    <span class="hljs-attr">"@react-mf/root-config"</span>: <span class="hljs-string">"https://react.microfrontends.app/root-config/e129469347bb89b7ff74bcbebb53cc0bb4f5e27f/react-mf-root-config.js"</span>,
    <span class="hljs-attr">"@react-mf/navbar"</span>: <span class="hljs-string">"https://react.microfrontends.app/navbar/631442f229de2401a1e7c7835dc7a56f7db606ea/react-mf-navbar.js"</span>,
    <span class="hljs-attr">"@react-mf/styleguide"</span>: <span class="hljs-string">"https://react.microfrontends.app/styleguide/f965d7d74e99f032c27ba464e55051ae519b05dd/react-mf-styleguide.js"</span>,
    <span class="hljs-attr">"@react-mf/people"</span>: <span class="hljs-string">"https://react.microfrontends.app/people/dd205282fbd60b09bb3a937180291f56e300d9db/react-mf-people.js"</span>,
    <span class="hljs-attr">"@react-mf/api"</span>: <span class="hljs-string">"https://react.microfrontends.app/api/2966a1ca7799753466b7f4834ed6b4f2283123c5/react-mf-api.js"</span>,
    <span class="hljs-attr">"@react-mf/planets"</span>: <span class="hljs-string">"https://react.microfrontends.app/planets/5f7fc62b71baeb7a0724d4d214565faedffd8f61/react-mf-planets.js"</span>,
    <span class="hljs-attr">"@react-mf/things"</span>: <span class="hljs-string">"https://react.microfrontends.app/things/7f209a1ed9ac9690835c57a3a8eb59c17114bb1d/react-mf-things.js"</span>,
    <span class="hljs-attr">"rxjs"</span>: <span class="hljs-string">"https://cdn.jsdelivr.net/npm/@esm-bundle/rxjs@6.5.5/system/rxjs.min.js"</span>,
    <span class="hljs-attr">"rxjs/operators"</span>: <span class="hljs-string">"https://cdn.jsdelivr.net/npm/@esm-bundle/rxjs@6.5.5/system/rxjs-operators.min.js"</span>
  }
}
</code></pre>
<p>That import map was the default one provided as an example when we used the CLI to generate our container app. What we need to do now is replace this example import map with an import map that actually references the bundles we’re using.</p>
<p>So, using the original import map as a template, we can create a new file called <code>importmap.json</code>, place it <em>outside of our repos</em> and add JSON that looks like this:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"imports"</span>: {
    <span class="hljs-attr">"react"</span>: <span class="hljs-string">"https://cdn.jsdelivr.net/npm/react@16.13.0/umd/react.production.min.js"</span>,
    <span class="hljs-attr">"react-dom"</span>: <span class="hljs-string">"https://cdn.jsdelivr.net/npm/react-dom@16.13.0/umd/react-dom.production.min.js"</span>,
    <span class="hljs-attr">"single-spa"</span>: <span class="hljs-string">"https://cdn.jsdelivr.net/npm/single-spa@5.5.1/lib/system/single-spa.min.js"</span>,
    <span class="hljs-attr">"@thawkin3/root-config"</span>: <span class="hljs-string">"https://single-spa-demo.s3-us-west-2.amazonaws.com/%40thawkin3/root-config/179ba4f2ce4d517bf461bee986d1026c34967141/root-config.js"</span>,
    <span class="hljs-attr">"@thawkin3/single-spa-demo-nav"</span>: <span class="hljs-string">"https://single-spa-demo.s3-us-west-2.amazonaws.com/%40thawkin3/single-spa-demo-nav/f0e9d35392ea0da8385f6cd490d6c06577809f16/thawkin3-single-spa-demo-nav.js"</span>,
    <span class="hljs-attr">"@thawkin3/single-spa-demo-page-1"</span>: <span class="hljs-string">"https://single-spa-demo.s3-us-west-2.amazonaws.com/%40thawkin3/single-spa-demo-page-1/4fd417ee3faf575fcc29d17d874e52c15e6f0780/thawkin3-single-spa-demo-page-1.js"</span>,
    <span class="hljs-attr">"@thawkin3/single-spa-demo-page-2"</span>: <span class="hljs-string">"https://single-spa-demo.s3-us-west-2.amazonaws.com/%40thawkin3/single-spa-demo-page-2/8c58a825c1552aab823bcbd5bdd13faf2bd4f9dc/thawkin3-single-spa-demo-page-2.js"</span>
  }
}
</code></pre>
<p>You’ll note that the first three imports are for shared dependencies: react, react-dom, and single-spa. That way we don’t have four copies of React in our app causing bloat and longer download times. Next, we have imports for each of our four apps. The URL is simply the URL for each uploaded file in S3 (called an “object” in AWS terminology).</p>
<p>Now that we have this file created, we can manually upload it to our bucket in S3 through the AWS console. </p>
<p><strong>Note</strong>: This is a pretty important and interesting caveat when using single-spa: The import map doesn’t actually live anywhere in source control or in any of the git repos. That way, the import map can be updated on the fly without requiring checked-in changes in a repo. We’ll come back to this concept in a little bit.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/07/mfe10.png" alt="Import map manually uploaded to the S3 bucket" width="600" height="400" loading="lazy">
<em>Import map manually uploaded to the S3 bucket</em></p>
<p>Finally, we can now reference this new file in our <code>index.ejs</code> file instead of referencing the original import map.</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"systemjs-importmap"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"//single-spa-demo.s3-us-west-2.amazonaws.com/%40thawkin3/importmap.json"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<h1 id="heading-creating-a-production-server">Creating a Production Server</h1>
<p>We are getting closer to having something up and running in production! We’re going to host this demo on Heroku, so in order to do that, we’ll need to create a simple Node.js and <a target="_blank" href="https://expressjs.com/">Express</a> server to serve our file.</p>
<p>First, in the <code>single-spa-demo-root-config</code> directory, we'll install express by running <code>yarn add express</code> (or <code>npm install express</code>). Next, we'll add a file called <code>server.js</code> that contains a small amount of code for starting up an express server and serving our main <code>index.html</code> file.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">"express"</span>);
<span class="hljs-keyword">const</span> path = <span class="hljs-built_in">require</span>(<span class="hljs-string">"path"</span>);
<span class="hljs-keyword">const</span> PORT = process.env.PORT || <span class="hljs-number">5000</span>;

express()
  .use(express.static(path.join(__dirname, <span class="hljs-string">"dist"</span>)))
  .get(<span class="hljs-string">"*"</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
    res.sendFile(<span class="hljs-string">"index.html"</span>, { <span class="hljs-attr">root</span>: <span class="hljs-string">"dist"</span> });
  })
  .listen(PORT, <span class="hljs-function">() =&gt;</span> <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Listening on <span class="hljs-subst">${PORT}</span>`</span>));
</code></pre>
<p>Finally, we’ll update the NPM scripts in our <code>package.json</code> file to differentiate between running the server in development mode and running the server in production mode.</p>
<pre><code class="lang-json"><span class="hljs-string">"scripts"</span>: {
  <span class="hljs-attr">"build"</span>: <span class="hljs-string">"webpack --mode=production"</span>,
  <span class="hljs-attr">"lint"</span>: <span class="hljs-string">"eslint src"</span>,
  <span class="hljs-attr">"prettier"</span>: <span class="hljs-string">"prettier --write './**'"</span>,
  <span class="hljs-attr">"start:dev"</span>: <span class="hljs-string">"webpack-dev-server --mode=development --port 9000 --env.isLocal=true"</span>,
  <span class="hljs-attr">"start"</span>: <span class="hljs-string">"node server.js"</span>,
  <span class="hljs-attr">"test"</span>: <span class="hljs-string">"jest"</span>
}
</code></pre>
<h1 id="heading-deploying-to-heroku">Deploying to Heroku</h1>
<p>Now that we have a production server ready, let’s get this thing deployed to Heroku! In order to do so, you’ll need to have a <a target="_blank" href="https://signup.heroku.com/">Heroku account created</a>, the <a target="_blank" href="https://devcenter.heroku.com/articles/heroku-cli">Heroku CLI</a> installed, and be logged in. Deploying to Heroku is as easy as 1–2–3:</p>
<ol>
<li>In the <code>single-spa-demo-root-config</code> directory: <code>heroku create thawkin3-single-spa-demo</code> (changing that last argument to a unique name to be used for your Heroku app)</li>
<li><code>git push heroku master</code></li>
<li><code>heroku open</code></li>
</ol>
<p>And with that, we are up and running in production. Upon running the <code>heroku open</code> command, you should see your app open in your browser. Try navigating between pages using the nav links to see the different micro-frontend apps mount and unmount.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/07/mfe11.png" alt="Demo app — up and running in production" width="600" height="400" loading="lazy">
<em>Demo app — up and running in production</em></p>
<h1 id="heading-making-updates">Making Updates</h1>
<p>At this point, you may be asking yourself, “All that work for this? Why?” And you’d be right. Sort of. This is a lot of work, and we don’t have much to show for it, at least not visually. But, we’ve laid the groundwork for whatever app improvements we’d like. </p>
<p>The setup cost for any microservice or micro-frontend is often a lot higher than the setup cost for a monolith; it’s not until later that you start to reap the rewards.</p>
<p>So let’s start thinking about future modifications. Let’s say that it’s now five or ten years later, and your app has grown. A lot. And, in that time, a hot new framework has been released, and you’re dying to re-write your entire app using that new framework. </p>
<p>When working with a monolith, this would likely be a years-long effort and may be nearly impossible to accomplish. But, with micro-frontends, you could swap out technologies one piece of the app at a time, allowing you to slowly and smoothly transition to a new tech stack. Magic!</p>
<p>Or, you may have one piece of your app that changes frequently and another piece of your app that is rarely touched. While making updates to the volatile app, wouldn’t it be nice if you could just leave the legacy code alone? </p>
<p>With a monolith, it’s possible that changes you make in one place of your app may affect other sections of your app. What if you modified some stylesheets that multiple sections of the monolith were using? Or what if you updated a dependency that was used in many different places? </p>
<p>With a micro-frontend approach, you can leave those worries behind, refactoring and updating one app where needed while leaving legacy apps alone.</p>
<p>But, how do you make these kinds of updates? Or updates of any sort, really? </p>
<p>Right now we have our production import map in our <code>index.ejs</code> file, but it's just pointing to the file we manually uploaded to our S3 bucket. If we wanted to release some new changes right now, we'd need to push new code for one of the micro-frontends, get a new build artifact, and then manually update the import map with a reference to the new JavaScript bundle.</p>
<p>Is there a way we could automate this? Yes!</p>
<h1 id="heading-updating-one-of-the-apps">Updating One of the Apps</h1>
<p>Let’s say we want to update our page 1 app to have different text showing. In order to automate the deployment of this change, we can update our CI pipeline to not only build an artifact and upload it to our S3 bucket, but to also update the import map to reference the new URL for the latest JavaScript bundle.</p>
<p>Let’s start by updating our <code>.travis.yml</code> file like so:</p>
<pre><code class="lang-yaml"><span class="hljs-attr">language:</span> <span class="hljs-string">node_js</span>
<span class="hljs-attr">node_js:</span>
  <span class="hljs-bullet">-</span> <span class="hljs-string">node</span>
<span class="hljs-attr">env:</span>
  <span class="hljs-attr">global:</span>
    <span class="hljs-comment"># include $HOME/.local/bin for `aws`</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">PATH=$HOME/.local/bin:$PATH</span>
<span class="hljs-attr">before_install:</span>
  <span class="hljs-bullet">-</span> <span class="hljs-string">pyenv</span> <span class="hljs-string">global</span> <span class="hljs-number">3.7</span><span class="hljs-number">.1</span>
  <span class="hljs-bullet">-</span> <span class="hljs-string">pip</span> <span class="hljs-string">install</span> <span class="hljs-string">-U</span> <span class="hljs-string">pip</span>
  <span class="hljs-bullet">-</span> <span class="hljs-string">pip</span> <span class="hljs-string">install</span> <span class="hljs-string">awscli</span>
<span class="hljs-attr">script:</span>
  <span class="hljs-bullet">-</span> <span class="hljs-string">yarn</span> <span class="hljs-string">build</span>
  <span class="hljs-bullet">-</span> <span class="hljs-string">echo</span> <span class="hljs-string">"Commit sha - $TRAVIS_COMMIT"</span>
  <span class="hljs-bullet">-</span> <span class="hljs-string">mkdir</span> <span class="hljs-string">-p</span> <span class="hljs-string">dist/@thawkin3/root-config/$TRAVIS_COMMIT</span>
  <span class="hljs-bullet">-</span> <span class="hljs-string">mv</span> <span class="hljs-string">dist/*.*</span> <span class="hljs-string">dist/@thawkin3/root-config/$TRAVIS_COMMIT/</span>
<span class="hljs-attr">deploy:</span>
  <span class="hljs-attr">provider:</span> <span class="hljs-string">s3</span>
  <span class="hljs-attr">access_key_id:</span> <span class="hljs-string">"$AWS_ACCESS_KEY_ID"</span>
  <span class="hljs-attr">secret_access_key:</span> <span class="hljs-string">"$AWS_SECRET_ACCESS_KEY"</span>
  <span class="hljs-attr">bucket:</span> <span class="hljs-string">"single-spa-demo"</span>
  <span class="hljs-attr">region:</span> <span class="hljs-string">"us-west-2"</span>
  <span class="hljs-attr">cache-control:</span> <span class="hljs-string">"max-age=31536000"</span>
  <span class="hljs-attr">acl:</span> <span class="hljs-string">"public_read"</span>
  <span class="hljs-attr">local_dir:</span> <span class="hljs-string">dist</span>
  <span class="hljs-attr">skip_cleanup:</span> <span class="hljs-literal">true</span>
  <span class="hljs-attr">on:</span>
    <span class="hljs-attr">branch:</span> <span class="hljs-string">master</span>
<span class="hljs-attr">after_deploy:</span>
  <span class="hljs-bullet">-</span> <span class="hljs-string">chmod</span> <span class="hljs-string">+x</span> <span class="hljs-string">after_deploy.sh</span>
  <span class="hljs-bullet">-</span> <span class="hljs-string">"./after_deploy.sh"</span>
</code></pre>
<p>The main changes here are adding a global environment variable, installing the AWS CLI, and adding an <code>after_deploy</code> script as part of the pipeline. This references an <code>after_deploy.sh</code> file that we need to create. The contents will be:</p>
<pre><code class="lang-sh"><span class="hljs-built_in">echo</span> <span class="hljs-string">"Downloading import map from S3"</span>
aws s3 cp s3://single-spa-demo/@thawkin3/importmap.json importmap.json
<span class="hljs-built_in">echo</span> <span class="hljs-string">"Updating import map to point to new version of @thawkin3/root-config"</span>
node update-importmap.mjs
<span class="hljs-built_in">echo</span> <span class="hljs-string">"Uploading new import map to S3"</span>
aws s3 cp importmap.json s3://single-spa-demo/@thawkin3/importmap.json --cache-control <span class="hljs-string">'public, must-revalidate, max-age=0'</span> --acl <span class="hljs-string">'public-read'</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">"Deployment successful"</span>
</code></pre>
<p>This file downloads the existing import map from S3, modifies it to reference the new build artifact, and then re-uploads the updated import map to S3. To handle the actual updating of the import map file’s contents, we use a custom script that we’ll add in a file called <code>update-importmap.mjs.</code></p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Note that this file requires node@13.2.0 or higher (or the --experimental-modules flag)</span>
<span class="hljs-keyword">import</span> fs <span class="hljs-keyword">from</span> <span class="hljs-string">"fs"</span>;
<span class="hljs-keyword">import</span> path <span class="hljs-keyword">from</span> <span class="hljs-string">"path"</span>;
<span class="hljs-keyword">import</span> https <span class="hljs-keyword">from</span> <span class="hljs-string">"https"</span>;

<span class="hljs-keyword">const</span> importMapFilePath = path.resolve(process.cwd(), <span class="hljs-string">"importmap.json"</span>);
<span class="hljs-keyword">const</span> importMap = <span class="hljs-built_in">JSON</span>.parse(fs.readFileSync(importMapFilePath));
<span class="hljs-keyword">const</span> url = <span class="hljs-string">`https://single-spa-demo.s3-us-west-2.amazonaws.com/%40thawkin3/root-config/<span class="hljs-subst">${process.env.TRAVIS_COMMIT}</span>/root-config.js`</span>;

https
  .get(url, <span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> {
    <span class="hljs-comment">// HTTP redirects (301, 302, etc) not currently supported, but could be added</span>
    <span class="hljs-keyword">if</span> (res.statusCode &gt;= <span class="hljs-number">200</span> &amp;&amp; res.statusCode &lt; <span class="hljs-number">300</span>) {
      <span class="hljs-keyword">if</span> (
        res.headers[<span class="hljs-string">"content-type"</span>] &amp;&amp;
        res.headers[<span class="hljs-string">"content-type"</span>].toLowerCase().trim() ===
          <span class="hljs-string">"application/javascript"</span>
      ) {
        <span class="hljs-keyword">const</span> moduleName = <span class="hljs-string">`@thawkin3/root-config`</span>;
        importMap.imports[moduleName] = url;
        fs.writeFileSync(importMapFilePath, <span class="hljs-built_in">JSON</span>.stringify(importMap, <span class="hljs-literal">null</span>, <span class="hljs-number">2</span>));
        <span class="hljs-built_in">console</span>.log(
          <span class="hljs-string">`Updated import map for module <span class="hljs-subst">${moduleName}</span>. New url is <span class="hljs-subst">${url}</span>.`</span>
        );
      } <span class="hljs-keyword">else</span> {
        urlNotDownloadable(
          url,
          <span class="hljs-built_in">Error</span>(<span class="hljs-string">`Content-Type response header must be application/javascript`</span>)
        );
      }
    } <span class="hljs-keyword">else</span> {
      urlNotDownloadable(
        url,
        <span class="hljs-built_in">Error</span>(<span class="hljs-string">`HTTP response status was <span class="hljs-subst">${res.statusCode}</span>`</span>)
      );
    }
  })
  .on(<span class="hljs-string">"error"</span>, <span class="hljs-function"><span class="hljs-params">err</span> =&gt;</span> {
    urlNotDownloadable(url, err);
  });

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">urlNotDownloadable</span>(<span class="hljs-params">url, err</span>) </span>{
  <span class="hljs-keyword">throw</span> <span class="hljs-built_in">Error</span>(
    <span class="hljs-string">`Refusing to update import map - could not download javascript file at url <span class="hljs-subst">${url}</span>. Error was '<span class="hljs-subst">${err.message}</span>'`</span>
  );
}
</code></pre>
<p>Note that we need to make these changes for these three files in all of our GitHub repos so that each one is able to update the import map after creating a new build artifact. </p>
<p>The file contents will be nearly identical for each repo, but we’ll need to change the app names or URL paths to the appropriate values for each one.</p>
<h3 id="heading-a-side-note-on-the-import-map">A Side Note on the Import Map</h3>
<p>Earlier I mentioned that the import map file we manually uploaded to S3 doesn’t actually live anywhere in any of our GitHub repos or in any of our checked-in code. If you’re like me, this probably seems really odd! Shouldn’t everything be in source control?</p>
<p>The reason it’s not in source control is so that our CI pipeline can handle updating the import map with each new micro-frontend app release. </p>
<p>If the import map were in source control, making an update to one micro-frontend app would require changes in two repos: the micro-frontend app repo where the change is made, and the root config repo where the import map would be checked in. This sort of setup would invalidate one of micro-frontend architecture’s main benefits, which is that each app can be deployed completely independent of the other apps. </p>
<p>In order to achieve some level of source control on the import map, we can always use S3’s versioning feature for our bucket.</p>
<h1 id="heading-moment-of-truth">Moment of Truth</h1>
<p>With those modifications to our CI pipelines in place, it’s time for the final moment of truth: Can we update one of our micro-frontend apps, deploy it independently, and then see those changes take effect in production without having to touch any of our other apps?</p>
<p>In the <code>single-spa-demo-page-1</code> directory, in the <code>root.component.js</code> file, let's change the text from "Page 1 App" to "Page 1 App - UPDATED!" Next, let's commit that change and push and merge it to master. </p>
<p>This will kick off the Travis CI pipeline to build the new page 1 app artifact and then update the import map to reference that new file URL.</p>
<p>If we then navigate in our browser to <a target="_blank" href="https://thawkin3-single-spa-demo.herokuapp.com/page1">https://thawkin3-single-spa-demo.herokuapp.com/page1</a>, we’ll now see… drum roll please… our updated app!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/07/mfe12.png" alt="Demo app — successfully updating one of the micro-frontend apps" width="600" height="400" loading="lazy">
<em>Demo app — successfully updating one of the micro-frontend apps</em></p>
<h1 id="heading-conclusion">Conclusion</h1>
<p>I said it before, and I’ll say it again: <strong>Micro-frontends are the future of frontend web development.</strong> </p>
<p>The benefits are massive, including independent deployments, independent areas of ownership, faster build and test times, and the ability to mix and match various frameworks if needed. </p>
<p>There are some drawbacks, such as the initial set up cost and the complexity of maintaining a distributed architecture, but I strongly believe the benefits outweigh the costs.</p>
<p>Single-spa makes micro-frontend architecture easy. Now you, too, can go break up the monolith!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ What is the JAMstack and how do I get started? ]]>
                </title>
                <description>
                    <![CDATA[ JAMstack sites are all the rage right now in the web dev world. And rightfully so! But what exactly is it and how can we all take advantage of its benefits? What is this JAMstack? That’s not to be confused with serverless What makes up the JAMstack?... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/what-is-the-jamstack-and-how-do-i-host-my-website-on-it/</link>
                <guid isPermaLink="false">66b8e3a0682e4a25eed261a4</guid>
                
                    <category>
                        <![CDATA[ architecture ]]>
                    </category>
                
                    <category>
                        <![CDATA[ front end ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Front-end Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ frontend ]]>
                    </category>
                
                    <category>
                        <![CDATA[ HTML ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JAMstack ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ software architecture ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Colby Fayock ]]>
                </dc:creator>
                <pubDate>Wed, 19 Feb 2020 15:45:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/02/what-is-jamstack-2.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>JAMstack sites are all the rage right now in the web dev world. And rightfully so! But what exactly is it and how can we all take advantage of its benefits?</p>
<ul>
<li><a class="post-section-overview" href="#heading-what-is-this-jamstack">What is this JAMstack?</a></li>
<li><a class="post-section-overview" href="#heading-thats-not-to-be-confused-with-serverless">That’s not to be confused with serverless</a></li>
<li><a class="post-section-overview" href="#heading-what-makes-up-the-jamstack">What makes up the JAMstack?</a></li>
<li><a class="post-section-overview" href="#heading-so-what-makes-a-jamstack-app-so-great">So what makes a JAMstack app so great?</a></li>
<li><a class="post-section-overview" href="#heading-is-my-website-considered-to-be-on-the-jamstack">Is my website considered to be on the JAMstack?</a></li>
<li><a class="post-section-overview" href="#heading-what-are-some-examples-of-jamstack">What are some examples of JAMstack?</a></li>
<li><a class="post-section-overview" href="#heading-what-are-some-tools-i-can-use-to-build-jamstack-sites-or-apps">What are some tools I can use to build JAMstack sites or apps?</a></li>
</ul>
<h2 id="heading-what-is-this-jamstack">What is this JAMstack?</h2>
<p>To start, <a target="_blank" href="https://jamstack.org/">JAMstack</a> is a software architecture and philosophy that adheres to the following components: Javascript, APIs, and Markup.</p>
<p>If this sounds familiar, it's because it is! That React app that you compile down with <a target="_blank" href="https://webpack.js.org/">Webpack</a> and ultimately serve from <a target="_blank" href="https://aws.amazon.com/s3/">S3</a>? Yup, that’s a JAMstack app. That simple HTML file that has no JavaScript and literally doesn’t do anything dynamic? Yup, that’s also a JAMstack app.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/02/bill-ted-air-guitar.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Bill and Ted play air guitars</em></p>
<h2 id="heading-thats-not-to-be-confused-with-serverless">That’s not to be confused with serverless</h2>
<p>If you’re coming more from the cloud side of things (think <a target="_blank" href="https://aws.amazon.com/">AWS</a>, <a target="_blank" href="https://cloud.google.com/">GCP</a>, <a target="_blank" href="https://azure.microsoft.com/">Azure</a>), you might be inclined to think of <a target="_blank" href="https://serverless-stack.com/chapters/what-is-serverless.html">serverless</a> and JAMstack as the same thing. Granted they have similarities in the philosophy of how resources are managed, such as hosting a site on S3. But a JAMstack app is not always going to be a serverless app.</p>
<p>Consider an app hosted in static storage on the cloud provider of your choice. Yes, you might be serving the app in a serverless way, but you might be dealing with an API that utilizes Wordpress or Rails, both of which are certainly not serverless.</p>
<p>Combining these philosophies can go a long way, but they shouldn’t be confused as the same.</p>
<h2 id="heading-what-makes-up-the-jamstack">What makes up the JAMstack?</h2>
<p>Back to the JAMstack: it's typically comprised of 3 components: Javascript, APIs, and Markup. Its <a target="_blank" href="https://snipcart.com/blog/jamstack">history stems</a> from growing the term "static site" into something more meaningful (and marketable). So while ultimately a static site is the end result, it's blown up to include first class tooling for every step of the way.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/02/jamstack-breakdown-3.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>JAMstack breakdown</em></p>
<p>While there aren't any specific set of tools that you need to use, or any tools at all beyond simple HTML, there are great examples of what can make up each part of the stack. Let's dive in a little bit to each component.</p>
<h3 id="heading-javascript">Javascript</h3>
<p>The component that’s probably done the most work to popularize the JAMstack is Javascript. Our favorite browser language allows us to provide all of the dynamic and interactive bits that we might not have if we’re serving plain HTML without it.</p>
<p>This is where a lot of times you’ll see UI frameworks like <a target="_blank" href="https://reactjs.org/">React</a>, <a target="_blank" href="https://vuejs.org/">Vue</a>, and newcomers like <a target="_blank" href="https://svelte.dev/">Svelte</a> come into play.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/02/react-component-example.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>"A Simple Component" example from <a target="_blank" href="https://reactjs.org/">reactjs.org </a></em></p>
<p>They make building apps simpler and more organized by providing component APIs and tooling that compile down to a simple HTML file (or a bunch of them). </p>
<p>Those HTML files include a group of assets like images, CSS, and the actual JS that ultimately get served to a browser via your favorite CDN (content delivery network).</p>
<h3 id="heading-apis">APIs</h3>
<p>Utilizing the strengths of APIs is core to how you make a JAMstack app dynamic. Whether it’s authentication or search, your application will use Javascript to make an HTTP request to another provider which will ultimately enhance the experience in one form or another.</p>
<p><a target="_blank" href="https://www.gatsbyjs.org/">Gatsby</a> coined the phrase "<a target="_blank" href="https://www.gatsbyjs.org/blog/2018-10-04-journey-to-the-content-mesh/">content mesh</a>" that does a pretty good job at describing the possibilities here.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/02/content-mesh-1.jpg" alt="Image" width="600" height="400" loading="lazy">
<em><a target="_blank" href="https://www.gatsbyjs.org/blog/2018-10-04-journey-to-the-content-mesh/">Content Mesh</a></em></p>
<p>You don’t necessarily have to reach out to only one host for an API, but you can reach out to as many as you need (but try not to go overboard).</p>
<p>For instance, if you have a headless <a target="_blank" href="https://wordpress.org/">Wordpress</a> API where you host your blog posts, a <a target="_blank" href="https://cloudinary.com/">Cloudinary</a> account where you store your specialized media, and an <a target="_blank" href="https://www.elastic.co/">Elasticsearch</a> instance that provides your search functionality, they all work together to provide a single experience to the people using your site.</p>
<h3 id="heading-markup">Markup</h3>
<p>This is the critical piece. Whether it’s your hand written HTML or the code that compiles down to the HTML, it's the first part you’re serving to the client. This is kind of a de facto piece of any website, but how you serve it is the most important piece.</p>
<p>To be considered a JAMstack app, the HTML needs to be served statically, which basically means not being dynamically rendered from a server. </p>
<p>If you’re piecing a page together and serving it with PHP, it’s probably not a JAMstack app. If you upload and serve a single HTML file from storage that constructs an app with Javascript, it sounds like a JAMstack app.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/02/aws-s3-static-files-gatsby.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Static output from Gatsby on AWS S3</em></p>
<p>But that doesn’t mean we have to always build 100% of the app within the browser. Tools like Gatsby and other <a target="_blank" href="https://www.staticgen.com/">static site generators</a> allow us to pull in some or all of our API sources at build time and render the pages out as HTML files.</p>
<p>Think if you have a Wordpress blog, we can pull in all of the posts and ultimately create a new HTML file for each post. That means we’re going to be able to serve a precompiled version of the page directly to the browser which usually equates to a quicker <a target="_blank" href="https://developers.google.com/web/tools/lighthouse/audits/first-contentful-paint">first paint</a> and faster experience for your visitor.</p>
<h3 id="heading-one-note-about-hosting">One note about "hosting"</h3>
<p>Using the term hosting here can be misleading if you’re new to the concept. Yeah, your site is technically getting hosted somewhere, but it’s not in the traditional sense. You don’t have a server that you’re maintaining where you upload your files to with an <a target="_blank" href="https://en.wikipedia.org/wiki/File_Transfer_Protocol">FTP</a> client like <a target="_blank" href="https://cyberduck.io/">Cyberduck</a>.</p>
<p>Instead, whether your doing it yourself with S3 or piping it into Netlify (which is actually <a target="_blank" href="https://www.netlify.com/blog/2018/05/14/how-netlify-migrated-to-a-fully-multi-cloud-infrastructure/">multi-cloud</a>), your HTML and static assets are getting served from object storage. On the tail end of that you typically have a CDN like <a target="_blank" href="https://www.cloudflare.com/">Cloudflare</a> which caches those files at locations all over the world making your pages load faster for the people visiting your site.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/02/cdn-distribution-map.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>CDN distribution map</em></p>
<h2 id="heading-so-what-makes-a-jamstack-app-so-great">So what makes a JAMstack app so great?</h2>
<p>JAMstack apps inherently satisfy most if not all of the <a target="_blank" href="https://aws.amazon.com/blogs/apn/the-5-pillars-of-the-aws-well-architected-framework/">5 pillars of the AWS Well-Architected Framework</a>. These are core concepts that AWS considers to deliver fast, secure, high-performing, resilient, and efficient infrastructure.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/02/aws-well-architected-framework.jpg" alt="Image" width="600" height="400" loading="lazy">
<em><a target="_blank" href="https://aws.amazon.com/architecture/well-architected/">AWS Well-Architected</a></em></p>
<p>Let’s see how…</p>
<h3 id="heading-speed">Speed</h3>
<p>The fact that you’re serving JAMstack apps as static files directly from a CDN (usually) makes it likely your app is going to load super fast. Gone are the days where the server has to spend time building the page before responding; now you serve the page as just plain HTML "as is" or with some type of client side hydration like you’d see with <a target="_blank" href="https://reactjs.org/">React</a>.</p>
<h3 id="heading-cost">Cost</h3>
<p>More often than not, JAMstack sites are going to run cheaper than their server side counterparts. Hosting static assets is cheap and now your page is being served at the same rate.</p>
<h3 id="heading-scalability">Scalability</h3>
<p>Since you’re serving your files off of static hosting, likely a CDN, that pretty much automatically gives you infinite scalability. Most providers will make this claim, meaning you’ll have no trouble letting any influx of people hitting your site in through the front door.</p>
<h3 id="heading-maintenance">Maintenance</h3>
<p>The foundation of your static site isn’t a server, meaning you don't need to maintain it. Whether it’s Netlify, S3, or any other provider, your static HTML, CSS, and JS are maintained for you headache-free.</p>
<h3 id="heading-security">Security</h3>
<p>Doubling down on the lack of server that you have to personally maintain, you don’t really need to worry as much about locking down ways for people to intrude. </p>
<p>Instead, you'll need to focus mostly on permissions to lock down private content and assure your users that their personal information isn't publicly available.</p>
<h3 id="heading-but-this-also-depends-on-your-apis">But this also depends on your APIs</h3>
<p>As much as these points strike true for the static aspects of your site, keep in mind you still might depend on some type of API for your client-side experience. </p>
<p>Try to take advantage of these requests at compile time when you can, such as with a static site generator. Otherwise you’ll need to weigh the amount of hits you’re making to a dynamic endpoint and how it impacts all of the points above for your overall experience.</p>
<h2 id="heading-is-my-website-considered-to-be-on-the-jamstack">Is my website considered to be on the JAMstack?</h2>
<p>We already talked about the 3 components (Javascript, APIs, Markup), but what we didn’t talk about is the fact that you don’t necessarily have to use all 3 of them in order to consider your site worthy of the JAM label.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/02/were-not-worthy.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Wayne's World "we're not worthy"</em></p>
<p>Really it all boils down to the Markup and how you serve it. Instead of your Rails app rendering your HTML for you, you might host a precompiled React app on S3 that reaches out to Rails via a set of APIs.</p>
<p>But you don’t even need to have APIs. You don’t even need to have Javascript! As long as you’re serving an HTML file without it having to be compiled on a server at request time (aka pre-rendering it), you’ve got yourself a JAMstack site.</p>
<h2 id="heading-what-are-some-examples-of-jamstack">What are some examples of JAMstack?</h2>
<h3 id="heading-freecodecamporg">freecodecamp.org</h3>
<p>Yes! freecodecamp.org and its learning portal <a target="_blank" href="https://www.freecodecamp.org/news/freecodecamp-jamstack/">is a JAMstack site</a> built on Gatsby. Even with the complexities of providing an app to take code courses with, freeCodeCamp is able to pull together the power of a static site generator and powerful APIs to bring people around the world the power of learning code.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/02/freecodecamp.jpg" alt="Image" width="600" height="400" loading="lazy">
<em><a target="_blank" href="https://www.freecodecamp.org/">https://www.freecodecamp.org/</a></em></p>
<p>You can see Quincy from freeCodeCamp talk more about this at the 2018 JAMstack_conf:<br><a target="_blank" href="https://www.youtube.com/watch?v=e5H7CI3yqPY">https://www.youtube.com/watch?v=e5H7CI3yqPY</a></p>
<p><em>Note: the News and Forum portals are not currently JAMstack sites.</em></p>
<h3 id="heading-impossible-foods">Impossible Foods</h3>
<p>The main website for <a target="_blank" href="https://impossiblefoods.com/">Impossible Foods</a> is no other than a Gatsby site! Everything from their recipes to their location finder are all compiled through our favorite "blazing fast" static site generator.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/02/impossible-foods.jpg" alt="Image" width="600" height="400" loading="lazy">
<em><a target="_blank" href="https://impossiblefoods.com/">https://impossiblefoods.com/</a></em></p>
<h3 id="heading-webdev">web.dev</h3>
<p>Google’s <a target="_blank" href="https://web.dev/">web.dev</a> resource center is built out using the growing <a target="_blank" href="https://www.11ty.dev/">11ty</a>. You can even find the code made open source at: <a target="_blank" href="https://github.com/GoogleChrome/web.dev">https://github.com/GoogleChrome/web.dev</a></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/02/google-web-dev-1.jpg" alt="Image" width="600" height="400" loading="lazy">
<em><a target="_blank" href="https://web.dev/">https://web.dev/</a></em></p>
<h2 id="heading-what-are-some-tools-i-can-use-to-build-jamstack-sites-or-apps">What are some tools I can use to build JAMstack sites or apps?</h2>
<p>The good news with all of this buzz is there are a ton of tools currently available and a ton more on the way. They might still be a little rough around the edges, but that’s because this is a brave new world of tooling and that takes some smoothing out to get just right.</p>
<h3 id="heading-constructing-your-app">Constructing your app</h3>
<p>This is the fun part. How are you going to build your app? With <a target="_blank" href="https://github.com/scullyio/scully">Scully</a> <a target="_blank" href="https://www.netlify.com/blog/2019/12/16/introducing-scully-the-angular-static-site-generator/">in the picture</a>, you can pretty much pick your favorite flavor of UI framework and get off the ground running. Here’s a few popular ones to get started, but by no means is it exhaustive.</p>
<ul>
<li><a target="_blank" href="https://www.11ty.dev/">11ty</a></li>
<li><a target="_blank" href="https://www.gatsbyjs.org/">Gatsby</a></li>
<li><a target="_blank" href="https://gohugo.io/">Hugo</a></li>
<li><a target="_blank" href="https://www.nift.cc/">Nift</a></li>
<li><a target="_blank" href="https://github.com/scullyio/scully">Scully</a> (for you Angular fans)</li>
<li><a target="_blank" href="https://www.staticgen.com">And many more…</a></li>
</ul>
<p><em>Need me to pick one?</em> Start with Gatsby and <a target="_blank" href="https://github.com/colbyfayock/gatsby-starter-sass">bootstrap with a simple starter</a>.</p>
<h3 id="heading-serving-your-app">Serving your app</h3>
<p>I like to think of this as the easy part depending on your setup. Tools like Netlify and Zeit make this a breeze to configure by hooking into your Github repo and building anytime a new commit gets pushed, but of course you have options like AWS if you want more control.</p>
<ul>
<li><a target="_blank" href="https://aws.amazon.com/getting-started/projects/host-static-website/">AWS</a></li>
<li><a target="_blank" href="https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blob-static-website">Azure</a></li>
<li><a target="_blank" href="https://cloud.google.com/storage/docs/hosting-static-website">GCP</a></li>
<li><a target="_blank" href="https://pages.github.com/">Github Pages</a></li>
<li><a target="_blank" href="https://www.netlify.com/">Netlify</a></li>
<li><a target="_blank" href="https://surge.sh/">Surge</a></li>
<li><a target="_blank" href="https://zeit.co/">Zeit</a></li>
</ul>
<p><em>Need me to pick one?</em> Start with Netlify and <a target="_blank" href="https://www.netlify.com/blog/2016/09/29/a-step-by-step-guide-deploying-on-netlify/">take 5 minutes to deploy</a> that Gatsby site.</p>
<h3 id="heading-making-your-app-dynamic">Making your app dynamic</h3>
<p>Really this can be anything that can be used as an API making requests from the browser. I’m not going to list a bunch of examples per type, but here are a few tools and places you can find some resources.</p>
<ul>
<li><a target="_blank" href="https://auth0.com/">Auth0</a> - Authentication</li>
<li><a target="_blank" href="https://cloudinary.com/">Cloudinary</a> - Media management</li>
<li><a target="_blank" href="https://analytics.google.com/analytics/web/#/">Google Analytics</a> - Web traffic analytics</li>
<li><a target="_blank" href="https://headlesscms.org/">headlesscms.org</a> - Endless list of headless CMSs</li>
<li><a target="_blank" href="https://www.sanity.io/">Sanity</a> - CMS</li>
<li><a target="_blank" href="https://serverless.com/">Serverless Framework</a> - DIY, easy to deploy serverless resources</li>
<li><a target="_blank" href="https://snipcart.com/">Snipcart</a> - Ecommerce</li>
<li><a target="_blank" href="https://stripe.com/">Stripe</a> - Payment management</li>
<li><a target="_blank" href="https://github.com/agarrharr/awesome-static-website-services">And a bunch of other resources…</a></li>
<li><a target="_blank" href="https://headlesscms.org/">And a bunch of other CMS choices…</a></li>
<li><a target="_blank" href="https://jamstack.wtf/">And some general info and tools...</a></li>
</ul>
<h3 id="heading-and-how-about-general-resources-to-learn">And how about general resources to learn?</h3>
<p>You can find a lot of resources to get up and running quickly in the JAMstack world.</p>
<ul>
<li><a target="_blank" href="https://www.freecodecamp.org/news/how-to-host-and-deploy-a-static-website-or-jamstack-app-to-s3-and-cloudfront/">How to host and deploy a static website or JAMstack app to AWS S3 and CloudFront</a> from me on freeCodeCamp</li>
<li><a target="_blank" href="https://www.netlify.com/blog/2016/02/24/a-step-by-step-guide-gatsby-on-netlify/">A Step-by-Step Guide: Gatsby on Netlify</a> from Netlify</li>
<li><a target="_blank" href="https://www.filamentgroup.com/lab/build-a-blog/">Build your own Blog from Scratch using Eleventy</a> from filament group</li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/a-beginners-guide-on-how-to-host-a-static-site-with-aws/">How to Host your Static Website with AWS - A Beginner's Guide</a> from freeCodeCamp</li>
<li><a target="_blank" href="https://snipcart.com/blog/hugo-tutorial-static-site-ecommerce">Hugo Tutorial: How to Build &amp; Host a (Very Fast) Static E-Commerce Site</a> from SnipCart</li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/building-jamstack-apps/">How to Build Authenticated Serverless JAMstack Apps with Gatsby and Netlify</a> from freeCodeCamp</li>
</ul>
<h2 id="heading-expect-to-see-more">Expect to see more</h2>
<p>Similar to its serverless counterpart, the days of JAMstack are young. As time goes on, we’ll be seeing the tooling mature and expand providing new exciting ways for us to quickly build fast sites that anyone can use.</p>
<p>Join in the conversation on Twitter and <a target="_blank" href="https://twitter.com/colbyfayock">let me know</a> what your favorite part of building a JAMstack site is!</p>
<h2 id="heading-missing-something">Missing something?</h2>
<p>Missing your favorite JAMstack tool or an awesome example? <a target="_blank" href="https://twitter.com/colbyfayock">Ping me on Twitter</a>!</p>
<div id="colbyfayock-author-card">
  <p>
    <a href="https://twitter.com/colbyfayock">
      <img src="https://res.cloudinary.com/fay/image/upload/w_2000,h_400,c_fill,q_auto,f_auto/w_1020,c_fit,co_rgb:007079,g_north_west,x_635,y_70,l_text:Source%20Sans%20Pro_64_line_spacing_-10_bold:Colby%20Fayock/w_1020,c_fit,co_rgb:383f43,g_west,x_635,y_6,l_text:Source%20Sans%20Pro_44_line_spacing_0_normal:Follow%20me%20for%20more%20JavaScript%252c%20UX%252c%20and%20other%20interesting%20things!/w_1020,c_fit,co_rgb:007079,g_south_west,x_635,y_70,l_text:Source%20Sans%20Pro_40_line_spacing_-10_semibold:colbyfayock.com/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_68,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_145,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_222,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_295,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/v1/social-footer-card" alt="Follow me for more Javascript, UX, and other interesting things!" width="2000" height="400" loading="lazy">
    </a>
  </p>
  <ul>
    <li>
      <a href="https://twitter.com/colbyfayock">? Follow Me On Twitter</a>
    </li>
    <li>
      <a href="https://youtube.com/colbyfayock">?️ Subscribe To My Youtube</a>
    </li>
    <li>
      <a href="https://www.colbyfayock.com/newsletter/">✉️ Sign Up For My Newsletter</a>
    </li>
  </ul>
</div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Unified Architecture – A Simpler Way to Build Full-Stack Apps ]]>
                </title>
                <description>
                    <![CDATA[ By Manuel Vila Modern full-stack apps – like single-page apps or mobile apps – usually have six layers data access backend model API server API client frontend model and user interface. By architecting in this way, you can achieve some characterist... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/full-stack-unified-architecture/</link>
                <guid isPermaLink="false">66d46040a326133d12440a37</guid>
                
                    <category>
                        <![CDATA[ architecture ]]>
                    </category>
                
                    <category>
                        <![CDATA[ full stack ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Node.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Mon, 09 Dec 2019 23:42:36 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2019/12/unified-architecture-2.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Manuel Vila</p>
<p>Modern full-stack apps – like single-page apps or mobile apps – usually have six layers</p>
<ul>
<li>data access</li>
<li>backend model</li>
<li>API server</li>
<li>API client</li>
<li>frontend model</li>
<li>and user interface.</li>
</ul>
<p>By architecting in this way, you can achieve some characteristics of a well-designed application, such as <a target="_blank" href="https://en.wikipedia.org/wiki/Separation_of_concerns">separation of concerns</a> or <a target="_blank" href="https://en.wikipedia.org/wiki/Loose_coupling">loose coupling</a>.</p>
<p>But this does not come without drawbacks. It usually comes at the cost of other important characteristics, like simplicity, <a target="_blank" href="<https://en.wikipedia.org/wiki/Cohesion_(computer_science)>">cohesion</a>, and agility.</p>
<p>It seems we can't have it all. We have to compromise.</p>
<p>The problem is that developers usually build each layer as a completely different world on its own.</p>
<p>Even if you implement the layers with the same language, they cannot communicate with one another very easily.</p>
<p>You would need a lot of <a target="_blank" href="https://en.wikipedia.org/wiki/Glue_code">glue code</a> to connect them all, and the <a target="_blank" href="https://en.wikipedia.org/wiki/Domain_model">domain model</a> gets duplicated across the stack. As a result, your development agility suffers dramatically.</p>
<p>For example, adding a simple field to a model often requires modifying all the layers of the stack. This can feel a bit ridiculous.</p>
<p>Well, I've been thinking a lot about this problem recently. And I believe I've found a way out.</p>
<p>Here's the trick: for sure, the layers of an application must be "physically" separated. But they don't need to be "logically" separated.</p>
<h2 id="heading-the-unified-architecture">The Unified Architecture</h2>
<p>
    <img src="https://liaison-blog.s3.dualstack.us-west-2.amazonaws.com/images/traditional-vs-unified-architecture.svg" alt="Traditional vs unified architecture" width="581" height="581" loading="lazy">
</p>

<p>In object-oriented programming, when we use inheritance, we get some classes that can be seen in two ways: physical and logical. What do I mean by that?</p>
<p>Let's imagine we have a class <code>B</code> that inherits from a class <code>A</code>. Then, <code>A</code> and <code>B</code> can be seen as two physical classes. But logically, they are not separated, and <code>B</code> can be seen as a logical class that composes the properties of <code>A</code> with its own properties.</p>
<p>For example, when we call a method in a class, we don't have to worry if the method is implemented in this class or a parent class. From the caller perspective, there is only one class to worry about. Parent and child are unified into a single logical class.</p>
<p>How about applying the same approach to the layers of an application? Wouldn't it be great if, for example, the frontend could somehow inherit from the backend?</p>
<p>Doing so, frontend and backend would be unified into a single logical layer. And that would remove all communication and sharing issues. Indeed, backend classes, attributes, and methods would be directly accessible from the frontend.</p>
<p>Of course, we don't usually want to expose the whole backend to the frontend. But the same goes for class inheritance, and there is an elegant solution that is called "private properties". Similarly, the backend could selectively expose some attributes and methods.</p>
<p>Being able to grasp all the layers of an application from one single unified world is not a small deal. It changes the game completely. It is like going from a 3D world to a 2D world. Everything gets a lot easier.</p>
<p><a target="_blank" href="https://liaison.dev/blog/articles/Do-We-Really-Need-to-Separate-the-Model-from-the-UI-9wogqr#composition-over-inheritance">Inheritance is not evil</a>. Yes, it can be misused, and in some languages, it can be pretty rigid. But when properly used, it is an invaluable mechanism in our toolbox.</p>
<p>We have a problem, though. As far as I know, there is no language allowing us to inherit classes across multiple execution environments. But we are programmers, aren't we? We can build everything we want, and we can extend the language to provide new capabilities.</p>
<p>But before we get to that, let's break down the stack to see how each layer can fit in a unified architecture.</p>
<h3 id="heading-data-access">Data Access</h3>
<p>For a majority of applications, the database can be abstracted using some sort of ORM. So, from the developer perspective, there is no data access layer to worry about.</p>
<p>For more ambitious applications, we might have to optimize database schemas and requests. But we don't want to clutter the backend model with these concerns, and this is where an additional layer may be appropriate.</p>
<p>We build a data access layer to implement the optimization concerns, and this usually happens late in the development cycle, if it ever happens.</p>
<p>Anyway, if we need such a layer, we can build it later. With cross-layer inheritance, we can add a data access layer on top of the backend model layer with almost no changes to the existing code.</p>
<h3 id="heading-backend-model">Backend Model</h3>
<p>Typically, a backend model layer handles the following responsibilities:</p>
<ul>
<li>Shaping the domain model.</li>
<li>Implementing business logic.</li>
<li>Handling the authorization mechanisms.</li>
</ul>
<p>For most backends, it's fine to implement them all in a single layer. But, if we want to handle some concerns separately, for example, we want to separate the authorization from the business logic, we can implement them in two layers that inherit from each other.</p>
<h3 id="heading-api-layers">API Layers</h3>
<p>To connect the frontend and the backend, we usually build a web API (REST, GraphQL, etc.), and that complicates everything.</p>
<p>The web API must be implemented on both sides: an API client in the frontend and an API server in the backend. That's two extra layers to worry about, and it usually leads to duplicate the whole domain model.</p>
<p>A web API is nothing more than glue code, and it is a pain in the ass to build. So, if we can avoid it, that's a massive improvement.</p>
<p>Fortunately, we can take advantage of cross-layer inheritance again. In a unified architecture, there is no web API to build. All we have to do is to inherit the frontend model from the backend model, and we are done.</p>
<p>However, there are still some good use cases for building a web API. That's when we need to expose a backend to some third-party developers, or when we need to integrate with some legacy systems.</p>
<p>But let's be honest, most applications don't have such a requirement. And when they do, it is easy to handle it afterward. We can simply implement the web API into a new layer that inherits from the backend model layer.</p>
<p>Further information on this topic can be found in <a target="_blank" href="https://liaison.dev/blog/articles/How-about-interoperability-oy3ugk">this article</a>.</p>
<h3 id="heading-frontend-model">Frontend Model</h3>
<p>Since the backend is the source of truth, it should implement all the business logic, and the frontend should not implement any. So, the frontend model is simply inherited from the backend model, with almost no additions.</p>
<h3 id="heading-user-interface">User Interface</h3>
<p>We usually implement the frontend model and the UI in two separate layers. But as I showed in <a target="_blank" href="https://liaison.dev/blog/articles/Do-We-Really-Need-to-Separate-the-Model-from-the-UI-9wogqr">this article</a>, it is not mandatory.</p>
<p>When the frontend model is made of classes, it is possible to encapsulate the views as simple methods. Don't worry if you don't see what I mean right now, it will become clearer in the example later on.</p>
<p>Since the frontend model is basically empty (see above), it is fine to implement the UI directly into it, so there is no user interface layer <em>per se</em>.</p>
<p>Implementing the UI in a separate layer is still needed when we want to support multiple platforms (e.g., a web app and a mobile app). But, since it is just a matter of inheriting a layer, that can come later in the development roadmap.</p>
<h3 id="heading-putting-everything-together">Putting Everything Together</h3>
<p>The unified architecture allowed us to unify six physical layers into one single logical layer:</p>
<ul>
<li>In a minimal implementation, data access is encapsulated into the backend model, and the same goes for UI that is encapsulated into the frontend model.</li>
<li>The frontend model inherits from the backend model.</li>
<li>The API layers are not required anymore.</li>
</ul>
<p>Again, here's what the resulting implementation looks like:</p>
<p>
    <img src="https://liaison-blog.s3.dualstack.us-west-2.amazonaws.com/images/traditional-vs-unified-architecture.svg" alt="Traditional vs unified architecture" width="581" height="581" loading="lazy">
</p>

<p>That's pretty spectacular, don't you think?</p>
<h2 id="heading-liaison">Liaison</h2>
<p>To implement a unified architecture, all we need is cross-layer inheritance, and I started building <a target="_blank" href="https://liaison.dev">Liaison</a> to achieve exactly that.</p>
<p>You can see Liaison as a framework if you wish, but I prefer to describe it as a language extension because all its features lie at the lowest possible level — the programming language level.</p>
<p>So, Liaison does not lock you into a predefined framework, and a whole universe can be created on top of it. You can read more on this topic in <a target="_blank" href="https://liaison.dev/blog/articles/Getting-the-Right-Level-of-Generalization-7xpk37">this article</a>.</p>
<p>Behind the scene, Liaison relies on an <a target="_blank" href="https://en.wikipedia.org/wiki/Remote_procedure_call">RPC</a> mechanism. So, superficially, it can be seen as something like <a target="_blank" href="https://en.wikipedia.org/wiki/Common_Object_Request_Broker_Architecture">CORBA</a>, <a target="_blank" href="https://en.wikipedia.org/wiki/Java_remote_method_invocation">Java RMI</a>, or <a target="_blank" href="https://en.wikipedia.org/wiki/Windows_Communication_Foundation">.NET CWF</a>.</p>
<p>But Liaison is radically different:</p>
<ul>
<li>It is not a <a target="_blank" href="https://en.wikipedia.org/wiki/Distributed_object">distributed object system</a>. Indeed, a Liaison backend is stateless, so there are no shared objects across layers.</li>
<li>It is implemented at the language-level (see above).</li>
<li>Its design is straightforward and it exposes a minimal API.</li>
<li>It doesn't involve any boilerplate code, generated code, configuration files, or artifacts.</li>
<li>It uses a simple but powerful serialization protocol (<a target="_blank" href="https://deepr.io">Deepr</a>) that enables unique features, such as chained invocation, automatic batching, or partial execution.</li>
</ul>
<p>Liaison starts its journey in JavaScript, but the problem it tackles is universal, and it could be ported to any object-oriented language without too much trouble.</p>
<h3 id="heading-hello-counter">Hello Counter</h3>
<p>Let's illustrate how Liaison works by implementing the classic "Counter" example as a single-page application.</p>
<p>First, we need some shared code between the frontend and the backend:</p>
<pre><code class="lang-js"><span class="hljs-comment">// shared.js</span>

<span class="hljs-keyword">import</span> {Model, field} <span class="hljs-keyword">from</span> <span class="hljs-string">'@liaison/liaison'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Counter</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Model</span> </span>{
  <span class="hljs-comment">// The shared class defines a field to keep track of the counter's value</span>
  @field(<span class="hljs-string">'number'</span>) value = <span class="hljs-number">0</span>;
}
</code></pre>
<p>Then, let's build the backend to implement the business logic:</p>
<pre><code class="lang-js"><span class="hljs-comment">// backend.js</span>

<span class="hljs-keyword">import</span> {Layer, expose} <span class="hljs-keyword">from</span> <span class="hljs-string">'@liaison/liaison'</span>;

<span class="hljs-keyword">import</span> {Counter <span class="hljs-keyword">as</span> BaseCounter} <span class="hljs-keyword">from</span> <span class="hljs-string">'./shared'</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Counter</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">BaseCounter</span> </span>{
  <span class="hljs-comment">// We expose the `value` field to the frontend</span>
  @expose({<span class="hljs-attr">get</span>: <span class="hljs-literal">true</span>, <span class="hljs-attr">set</span>: <span class="hljs-literal">true</span>}) value;

  <span class="hljs-comment">// And we expose the `increment()` method as well</span>
  @expose({<span class="hljs-attr">call</span>: <span class="hljs-literal">true</span>}) increment() {
    <span class="hljs-built_in">this</span>.value++;
  }
}

<span class="hljs-comment">// We register the backend class into an exported layer</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> backendLayer = <span class="hljs-keyword">new</span> Layer({Counter});
</code></pre>
<p>Finally, let's build the frontend:</p>
<pre><code class="lang-js"><span class="hljs-comment">// frontend.js</span>

<span class="hljs-keyword">import</span> {Layer} <span class="hljs-keyword">from</span> <span class="hljs-string">'@liaison/liaison'</span>;

<span class="hljs-keyword">import</span> {Counter <span class="hljs-keyword">as</span> BaseCounter} <span class="hljs-keyword">from</span> <span class="hljs-string">'./shared'</span>;
<span class="hljs-keyword">import</span> {backendLayer} <span class="hljs-keyword">from</span> <span class="hljs-string">'./backend'</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Counter</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">BaseCounter</span> </span>{
  <span class="hljs-comment">// For now, the frontend class is just inheriting the shared class</span>
}

<span class="hljs-comment">// We register the frontend class into a layer that inherits from the backend layer</span>
<span class="hljs-keyword">const</span> frontendLayer = <span class="hljs-keyword">new</span> Layer({Counter}, {<span class="hljs-attr">parent</span>: backendLayer});

<span class="hljs-comment">// Lastly, we can instantiate a counter</span>
<span class="hljs-keyword">const</span> counter = <span class="hljs-keyword">new</span> frontendLayer.Counter();

<span class="hljs-comment">// And play with it</span>
<span class="hljs-keyword">await</span> counter.increment();
<span class="hljs-built_in">console</span>.log(counter.value); <span class="hljs-comment">// =&gt; 1</span>
</code></pre>
<p>What's going on? By invoking <code>counter.increment()</code>, we got the counter's value incremented. Notice that the <code>increment()</code> method is neither implemented in the frontend class nor in the shared class. It only exists in the backend.</p>
<p>So, how is it possible that we could call it from the frontend? This is because the frontend class is registered in a layer that inherits from the backend layer. So, when a method is missing in the frontend class, and a method with the same name is exposed in the backend class, it is automatically invoked.</p>
<p>From the frontend point of view, the operation is transparent. It doesn't need to know that a method is invoked remotely. It just works.</p>
<p>The current state of an instance (i.e., <code>counter</code>'s attributes) is automatically transported back and forth. When a method is executed in the backend, the attributes that have been modified in the frontend are sent. And inversely, when some attributes change in the backend, they are reflected in the frontend.</p>
<blockquote>
<p>Note that in this simple example, the backend is not exactly remote. Both the frontend and the backend run in the same JavaScript runtime. To make the backend truly remote, we can easily expose it through HTTP. See an <a target="_blank" href="https://github.com/liaisonjs/liaison/tree/master/examples/counter-via-http/src">example here</a>.</p>
</blockquote>
<p>How about passing/returning values to/from a remotely invoked method? It is possible to pass/return anything that is serializable, including class instances. As long as a class is registered with the same name in both the frontend and the backend, its instances can be automatically transported.</p>
<p>How about overriding a method across the frontend and the backend? It is no different than with regular JavaScript – we can use <code>super</code>. For example, we can override the <code>increment()</code> method to run additional code in the context of the frontend:</p>
<pre><code class="lang-js"><span class="hljs-comment">// frontend.js</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Counter</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">BaseCounter</span> </span>{
  <span class="hljs-keyword">async</span> increment() {
    <span class="hljs-keyword">await</span> <span class="hljs-built_in">super</span>.increment(); <span class="hljs-comment">// Backend's `increment()` method is invoked</span>
    <span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">this</span>.value); <span class="hljs-comment">// Additional code is executed in the frontend</span>
  }
}
</code></pre>
<p>Now, let's build a user interface with <a target="_blank" href="https://reactjs.org/">React</a> and the encapsulated approach shown earlier:</p>
<pre><code class="lang-js"><span class="hljs-comment">// frontend.js</span>

<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> {view} <span class="hljs-keyword">from</span> <span class="hljs-string">'@liaison/react-integration'</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Counter</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">BaseCounter</span> </span>{
  <span class="hljs-comment">// We use the `@view()` decorator to observe the model and re-render the view when needed</span>
  @view() View() {
    <span class="hljs-keyword">return</span> (
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
        {this.value} <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> this.increment()}&gt;+<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
  }
}
</code></pre>
<p>Finally, to display the counter, all we need is:</p>
<pre><code class="lang-js">&lt;counter.View /&gt;
</code></pre>
<p>Voilà! We built a single-page application with two unified layers and an encapsulated UI.</p>
<h3 id="heading-proof-of-concept">Proof of Concept</h3>
<p>To experiment with the unified architecture, I built a <a target="_blank" href="https://github.com/liaisonjs/react-liaison-realworld-example-app">RealWorld example app</a> with Liaison.</p>
<p>I might be biased, but the outcome looks pretty amazing to me: simple implementation, high code cohesion, 100% <a target="_blank" href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself">DRY</a>, and no glue code.</p>
<p>In terms of the amount of code, my implementation is significantly lighter than any other one I have examined. Check out the <a target="_blank" href="https://github.com/liaisonjs/react-liaison-realworld-example-app/blob/master/docs/comparison.md">results here</a>.</p>
<p>Certainly, the RealWorld example is a small application, but since it covers the most important concepts that are common to all applications, I'm confident that a unified architecture can scale up to more ambitious applications.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Separation of concerns, loose coupling, simplicity, cohesion, and agility.</p>
<p>It seems we get it all, finally.</p>
<p>If you are an experienced developer, I guess you feel a bit skeptical at this point, and this is totally fine. It is hard to leave behind years of established practices.</p>
<p>If object-oriented programming is not your cup of tea, you will not want to use Liaison, and this is totally fine as well.</p>
<p>But if you are into OOP, please keep a little window open in your mind, and the next time you have to build a full-stack application, try to see how it would fit in a unified architecture.</p>
<p><a target="_blank" href="https://liaison.dev/">Liaison</a> is still at an early stage, but I am actively working on it, and I expect to release the first beta version in early 2020.</p>
<p>If you are interested, please star the <a target="_blank" href="https://github.com/liaisonjs/liaison">repository</a> and stay updated by following the <a target="_blank" href="https://liaison.dev/blog">blog</a> or subscribing to the <a target="_blank" href="https://liaison.dev/#newsletter">newsletter</a>.</p>
<p><em>Discuss this article on <a target="_blank" href="https://changelog.com/news/how-to-simplify-fullstack-development-with-a-unified-architecture-XVOM">Changelog News</a></em>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Learn Software Design and Architecture - a Roadmap ]]>
                </title>
                <description>
                    <![CDATA[ By Khalil Stemmler This article is a summary of what I'm writing about in my newest project, solidbook.io - The Handbook to Software Design and Architecture with TypeScript. Check it out it you like this post. It's crazy to me to consider the fact ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/software-design/</link>
                <guid isPermaLink="false">66d45f6c868774922c884fea</guid>
                
                    <category>
                        <![CDATA[ architecture ]]>
                    </category>
                
                    <category>
                        <![CDATA[ software design ]]>
                    </category>
                
                    <category>
                        <![CDATA[ TypeScript ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Sun, 29 Sep 2019 18:17:54 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2019/09/banner-1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Khalil Stemmler</p>
<blockquote>
<p>This article is a summary of what I'm writing about in my newest project, <a target="_blank" href="https://solidbook.io">solidbook.io - The Handbook to Software Design and Architecture with TypeScript</a>. Check it out it you like this post.</p>
</blockquote>
<p>It's crazy to me to consider the fact that Facebook was once an empty text file on someone's computer.</p>
<p>Lol.</p>
<p>This past year, I've been going hard in software design and architecture, <a target="_blank" href="https://khalilstemmler.com/articles/domain-driven-design-intro/">Domain-Driven Design</a>, and <a target="_blank" href="https://solidbook.io">writing a book</a> on it, and I wanted to take a moment to try to piece it together into something useful I could share with the community.</p>
<p>Here's my roadmap for how to learn software design and architecture.</p>
<p>I've broken it down into two artifacts: the <strong>stack</strong> and the <strong>map</strong>.</p>
<h2 id="heading-the-stack">The Stack</h2>
<p>Similar to the <a target="_blank" href="https://en.wikipedia.org/wiki/OSI_model">OSI Model</a> in networking, each layer builds on top of the foundation of the previous one.</p>
<p><img src="https://thepracticaldev.s3.amazonaws.com/i/e727h5b9nozcuo4za2yw.png" alt="The stack" width="600" height="400" loading="lazy"></p>
<h2 id="heading-the-map">The Map</h2>
<p>While I think the stack is good to see the bigger picture of how everything works together, the map is a little bit more detailed (and inspired by the <a target="_blank" href="https://github.com/kamranahmedse/developer-roadmap">web developer roadmap</a>) and as a result, I think it's more useful.</p>
<p>Here it is below! To <a target="_blank" href="https://khalilstemmler.com/articles/software-design-architecture/full-stack-software-design/">fork the repo, read my detailed write-up and download it in  high-res, click here</a>.</p>
<p><img src="https://user-images.githubusercontent.com/6892666/65834517-bb39f980-e2a9-11e9-8a75-0e1559c5ed56.png" alt="Software Design and Architecture Roadmap" width="4424" height="17406" loading="lazy"></p>
<h2 id="heading-stage-1-clean-code">Stage 1: Clean code</h2>
<p>The very first step towards creating long-lasting software is figuring out how to write <strong>clean code</strong>. </p>
<p>Clean code is code that is easy to understand and change. At the low-level, this manifests in a few design choices like:</p>
<ul>
<li>being consistent</li>
<li>preferring meaningful variable, method and class names over writing comments</li>
<li>ensuring code is indented and spaced properly</li>
<li>ensuring all of the tests can run</li>
<li>writing pure functions with no side effects</li>
<li>not passing null </li>
</ul>
<p>Writing clean code is incredibly important. </p>
<p>Think of it like a game of jenga.</p>
<p>In order to keep the structure of our project stable over time, things like indentation, small classes and methods, and meaningful names, pay off a lot in the long run. </p>
<p>The best resource to learn how to write clean code is Uncle Bob's book, "<a target="_blank" href="https://www.amazon.ca/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882">Clean Code</a>".</p>
<h2 id="heading-stage-2-programming-paradigms">Stage 2: Programming Paradigms</h2>
<p>Now that we're writing readable code that's easy to maintain, it would be a good idea to really understand the 3 major programming paradigms and the way they influence how we write code.</p>
<p>In Uncle Bob's book, "<a target="_blank" href="https://www.amazon.ca/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882/ref=asc_df_0132350882/?tag=googleshopc0c-20&amp;linkCode=df0&amp;hvadid=292982483438&amp;hvpos=1o2&amp;hvnetw=g&amp;hvrand=13521899336201370454&amp;hvpone=&amp;hvptwo=&amp;hvqmt=&amp;hvdev=c&amp;hvdvcmdl=&amp;hvlocint=&amp;hvlocphy=9000834&amp;hvtargid=pla-435472505264&amp;psc=1">Clean Architecture</a>", he brings attention to the fact that:</p>
<ul>
<li>Object-Oriented Programming is the tool best suited for defining how we cross architectural boundaries with polymorhpism and plugins</li>
<li>Functional programming is the tool we use to push data to the boundaries of our applications</li>
<li>and Structured programming is the tool we use to write algorithms</li>
</ul>
<p>This implies that effective software uses a hybrid all 3 programming paradigms styles at different times.</p>
<p>While you <em>could</em> take a strictly functional or strictly object-oriented approach to writing code, understanding where each excels will improve the quality of your designs.</p>
<blockquote>
<p>If all you have is a hammer, everything seems like a nail.</p>
</blockquote>
<h3 id="heading-resources">Resources</h3>
<p>For <strong>functional programming</strong>, check out:</p>
<ul>
<li><a target="_blank" href="https://mostly-adequate.gitbooks.io/mostly-adequate-guide/">Professor Frisby's Mostly Adequate Guide to Functional Programming</a></li>
<li><a target="_blank" href="https://pragprog.com/book/swdddf/domain-modeling-made-functional?fbclid=IwAR0NHoyVrMoSRIE-EJMUOdsb3bhivow6JXKyUeg4FPHE8QmeOQG4L77HzMo">Domain Modeling Made Functional</a></li>
</ul>
<h2 id="heading-stage-3-object-oriented-programming">Stage 3: Object-Oriented Programming</h2>
<p>It's important to know how each of the paradigms work and how they urge you to structure the code within them, but with respect to architecture, Object-Oriented Programming is the clear <em>tool for the job</em>.</p>
<p>Not only does Object-Oriented programming enable us to create a <strong>plugin architecture</strong> and build flexibility into our projects; OOP comes with the 4 principles of OOP (encapsulation, inheritance, polymorhism, and abstraction) that help us create <strong>rich domain models</strong>.</p>
<p>Most developers learning Object-Oriented Programming never get to this part: learning how to create a <u>software implementation of the problem domain</u>, and locating it in the center of a <strong>layered</strong> web app. </p>
<p>Functional programming can seem like the means to all ends in this scenario, but  I'd recommend getting acquainted with model-driven design and <a target="_blank" href="https://khalilstemmler.com/articles/domain-driven-design-intro/">Domain-Driven Design</a> to understand the bigger picture on how object-modelers are able to encapsulate an entire business in a zero-dependency domain model.</p>
<blockquote>
<p>Why is that a huge deal?</p>
</blockquote>
<p>It's huge because if you can create a mental-model of a business, you can create a software implementation of that business.</p>
<h2 id="heading-stage-4-design-principles">Stage 4: Design Principles</h2>
<p>At this point, you're understanding that Object-Oriented Programming is very useful for encapsulating rich domain models and solving the <a target="_blank" href="https://khalilstemmler.com/wiki/3-categories-of-hard-software-problems/">3rd type of "Hard Software Problems"- Complex Domains</a>.</p>
<p>But OOP can introduce some design challenges. </p>
<p>When should I use composition?</p>
<p>When should I use inheritance?</p>
<p>When should I use an abstract class?</p>
<p>Design principles are really well-established and battle-tested object-oriented best practices that you use as railguards.</p>
<p>Some examples of common design principles you should familiarize yourself with are:</p>
<ul>
<li>Composition over inheritance</li>
<li>Encapsulate what varies</li>
<li>Program against abstractions, not concretions</li>
<li>The hollywood principle: "Don't call us, we'll call you"</li>
<li>The <a target="_blank" href="https://khalilstemmler.com/articles/solid-principles/solid-typescript/">SOLID principles</a>, especially the <a target="_blank" href="https://khalilstemmler.com/articles/solid-principles/single-responsibility/">Single responsibility principle</a></li>
<li>DRY (Do Not Repeat Yourself)</li>
<li><a target="_blank" href="https://khalilstemmler.com/wiki/yagni/">YAGNI (You Aren't Gonna Need It)</a></li>
</ul>
<p>Make sure to come to your <em>own</em> conclusions, though. Don't just follow what someone else says you should do. Make sure that it makes sense to you.</p>
<h2 id="heading-stage-5-design-patterns">Stage 5: Design Patterns</h2>
<p>Just about every problem in software has been categorized and solved already. We call these patterns: design patterns, actually.</p>
<p>There are 3 categories of design patterns: <strong>creational</strong>, <strong>structural</strong>, and <strong>behaviour</strong>.</p>
<h3 id="heading-creational">Creational</h3>
<p>Creational patterns are patterns that control how objects are created.</p>
<p>Examples of creational patterns include:</p>
<ul>
<li>The <strong>Singleton pattern</strong>, for ensuring only a single instance of a class can exist</li>
<li>The <strong>Abstract Factory pattern</strong>, for creating an instance of several families of classes</li>
<li>The <strong>Prototype pattern</strong>, for starting out with an instance that is cloned from an existing one</li>
</ul>
<h3 id="heading-structural">Structural</h3>
<p>Structural patterns are patterns that simplify how we define relationships between components.</p>
<p>Examples of structural design patterns include:</p>
<ul>
<li>The <strong>Adapter pattern</strong>, for creating an interface to enable classes that normally can't work together, to work together. </li>
<li>The <strong>Bridge pattern</strong>, for splitting a class that should actually be one or more, into a set of classes that belong to a hierarchy, enabling the implementations to be developed independently of each other.</li>
<li>The <strong>Decorator pattern</strong>, for adding responsibilities to objects dynamically.</li>
</ul>
<h3 id="heading-behavioural">Behavioural</h3>
<p>Behavioural patterns are common patterns for facilitating elegant communication between objects.</p>
<p>Examples of behavioural patterns are:</p>
<ul>
<li>The <strong>Template pattern</strong>, for deferring the exact steps of an algorithm to a subclass.</li>
<li>The <strong>Mediator pattern</strong>, for defining the exact communication channels allowed between classes. </li>
<li>The <strong>Observer pattern</strong>, for enabling classes to subscribe to something of interest, and to be notified when a change occurred.</li>
</ul>
<h3 id="heading-design-pattern-criticisms">Design pattern criticisms</h3>
<p>Design patterns are great and all, but sometimes they can an additional complexity to our designs. It's important to remember YAGNI and attempt to keep our designs as simple as possible. Only use design patterns when you're really sure you need them. You'll know when you will.</p>
<p>If we know what each of these patterns are, when to use them, and when to <em>not even bother</em> using them, we're in good shape to begin to understand how to architect larger systems.</p>
<p>The reason behind that is because <strong>architectural patterns are just design patterns blown-up in scale to the high-level</strong>, where design patterns are low-level implementations (closer to classes and functions).</p>
<h3 id="heading-resources-1">Resources</h3>
<p><a target="_blank" href="https://refactoring.guru/design-patterns">Refactoring Guru - Design Patterns</a></p>
<h2 id="heading-stage-6-architectural-principles">Stage 6: Architectural Principles</h2>
<p>Now we're at a higher level of thinking beyond the class level.</p>
<p>We now understand that the decisions we make towards organzing and building relationships between components at the high-level and the low-level, will have a significant impact on the maintainability, flexibility, and testability of our project.</p>
<p>Learn the guiding principles that helps you build in the flexibility that your codebase needs in order to be able to react to new features and requirements, with as little effort as possible.</p>
<p>Here's what I'd recommend learning right off the bat:</p>
<ul>
<li>Component design principles: <a target="_blank" href="https://khalilstemmler.com/wiki/stable-abstraction-principle/">The Stable Abstraction Principle</a>, <a target="_blank" href="https://khalilstemmler.com/wiki/stable-dependency-principle/">The Stable Dependency Principle</a>, and The Acyclic Dependency Principle, for how to organize components, their dependencies, when to couple them, and the implications of accidentally creating dependency cycles and relying on unstable components.</li>
<li><a target="_blank" href="https://khalilstemmler.com/articles/enterprise-typescript-nodejs/clean-nodejs-architecture/">Policy vs. Detail</a>, for understanding how to separate the rules of your application from the implementation details.</li>
<li>Boundaries, and how to identify the <a target="_blank" href="https://khalilstemmler.com/articles/enterprise-typescript-nodejs/application-layer-use-cases/">subdomains</a> that the features of your application belongs within.</li>
</ul>
<p>Uncle Bob discovered and originally documented many of these principles, so the best resource to learn about this is again, "<a target="_blank" href="https://www.amazon.ca/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882/ref=asc_df_0132350882/?tag=googleshopc0c-20&amp;linkCode=df0&amp;hvadid=292982483438&amp;hvpos=1o2&amp;hvnetw=g&amp;hvrand=13521899336201370454&amp;hvpone=&amp;hvptwo=&amp;hvqmt=&amp;hvdev=c&amp;hvdvcmdl=&amp;hvlocint=&amp;hvlocphy=9000834&amp;hvtargid=pla-435472505264&amp;psc=1">Clean Architecture</a>".</p>
<h2 id="heading-stage-7-architectural-styles">Stage 7: Architectural Styles</h2>
<p>Architecture is about the stuff that matters.</p>
<p>It's about identifying what a system needs in order for it to be successful, and then <u>stacking the odds of success</u> by choosing the architecture that best fits the requirements.</p>
<p>For example, a system that has a lot of <strong>business logic complexity</strong> would benefit from using a <strong>layered architecture</strong> to encapsulate that complexity.</p>
<p>A system like Uber needs to be able to handle a lot of <strong>real time-events</strong> at once and update drivers' locations, so <strong>publish-subscribe</strong> style architecture might be most effective.</p>
<p>I'll repeat myself here because it's important to note that the 3 categories of architectural styles are similar to the 3 categories of design patterns, because <strong>architectural styles are design patterns at the high-level</strong>.</p>
<h3 id="heading-structrual">Structrual</h3>
<p>Projects with <em>varying levels</em> of components and wide-ranging functionality will either benefit or suffer from adopting a structural architecture.</p>
<p>Here are a few examples:</p>
<ul>
<li><strong>Component-based</strong> architectures emphasize <u>separation of concerns</u> between the <em>individual components</em> within a system. Think <strong>Google</strong> for a sec. Consider how many applications they have within their enterprise (Google Docs, Google Drive, Google Maps, etc). For platforms with lots of functionality, component-based architectures divide the concerns into loosely coupled independent components. This is a <em>horizontal</em> separation. </li>
<li><strong>Monolithic</strong> means that the application is combined into a single platform or program, deployed altogether. <em>Note: You can have a component-based AND monolithic  architecture if you separate your applications properly, yet deploy it all as one piece</em>.</li>
<li><strong>Layered</strong> architectures separate the concerns <em>vertically</em> by cutting software into infrastructure, application, and domain layers.</li>
</ul>
<p><img src="https://khalilstemmler.com/img/blog/software-architecture-design/app-logic-layers.svg" alt="Clean Architecture" width="921" height="549" loading="lazy"></p>
<blockquote>
<p>An example of cutting the concerns of an application <em>vertically</em> by using a layered architecture. Read <a target="_blank" href="https://khalilstemmler.com/articles/software-design-architecture/organizing-app-logic/">here</a> for more information on how to do this.</p>
</blockquote>
<h3 id="heading-messaging">Messaging</h3>
<p>Depending on your project, messaging might be a really important component to the success of the system. For projects like this, message-based architectures build on top of functional programming principles and behavioural design patterns like the observer pattern.</p>
<p>Here are a few examples of message-based architectural styles:</p>
<ul>
<li><strong>Event-Driven</strong> architectures view all signficant changes to state as events. For example, within a <a target="_blank" href="https://github.com/stemmlerjs/white-label">vinyl-trading app</a>, a offer's state might change from "pending" to "accepted" when both parties agreee on the trade. </li>
<li><strong>Publish-subscribe</strong> architectures build on top of the Observer design pattern by making it the primary communication method between the system itself, end-users / clients, and others systems and components.</li>
</ul>
<h3 id="heading-distributed">Distributed</h3>
<p>A distributed architecture simply means that the components of the system are deployed separately and operate by communicating over a network protocol. Distributed systems can be very effective for scaling throughput, scaling teams, and delegating (potentially expensive tasks or) responsibility to other components.</p>
<p>A few examples of distributed architectural styles are:</p>
<ul>
<li><strong>Client-server</strong> architecture. One of the most common architectures, where we divide the work to be done between the client (presentation) and the server (business logic). </li>
<li><strong>Peer-to-peer</strong> architectures distribute application-layer tasks between equally-privileged participants, forming a peer-to-peer network. </li>
</ul>
<h2 id="heading-stage-8-architectural-patterns">Stage 8: Architectural Patterns</h2>
<p>Architectural <em>patterns</em> explain in greater tactical detail how to actually implement one of those architectural <em>styles</em>.</p>
<p>Here are a couple of examples of architectural patterns and the styles that they inherit from:</p>
<ul>
<li><strong><a target="_blank" href="https://khalilstemmler.com/articles/domain-driven-design-intro/">Domain-Driven Design</a></strong> is an approach to software development against really complex problem domains. For DDD to be most successful, we need to implement a <strong>layered architecture</strong> in order to separate the concerns of a domain model from the infrastrural details that makes the application actually run, like databases, webservers, caches, etc.</li>
<li><strong>Model-View Controller</strong> is probably the <u>most well-known</u> architectural pattern for developing user interface-based applications. It works by dividing the app into 3 components: model, view, and controller. MVC is incredibly useful when you're first starting out, and it helps you piggyback towards other architectures, but there hit's a point when we realize <a target="_blank" href="https://khalilstemmler.com/articles/enterprise-typescript-nodejs/when-crud-mvc-isnt-enough/">MVC isn't enough</a> for problems with lots of business logic.</li>
<li><strong>Event sourcing</strong> is a functional approach where we  store only the transactions, and never the state. If we ever need the state, we can apply all the transactions from the beginning of time.</li>
</ul>
<h2 id="heading-stage-9-enterprise-patterns">Stage 9: Enterprise patterns</h2>
<p>Any architectural pattern you choose will introduce a number of constructs and technical jargon to familiarize yourself with and decide on whether it's worth the effort to use or not.</p>
<p>Taking an example that many of us know, in <strong>MVC</strong>, the <em>view</em> holds all the presentation layer code, the <em>controller</em> is translates commands and queries from the <em>view</em> into requests that are handled by the <em>model</em> and returned by the <em>controller</em>.</p>
<p>Where in the Model (M) do we handle these things?:</p>
<ul>
<li>validation logic</li>
<li>invariant rules</li>
<li>domain events</li>
<li>use cases</li>
<li>complex queries</li>
<li>and business logic</li>
</ul>
<p>If we simply use an ORM (object-relational mapper) like <a target="_blank" href="">Sequelize</a> or <a target="_blank" href="">TypeORM</a> as the <em>model</em>, all that important stuff to gets left to interpretation on where it should go, and it finds itself in some unspecified layer between (what should be a rich) <em>model</em> and the <em>controller</em>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/10/mvc-2.svg" alt="mvc-2" width="600" height="400" loading="lazy"></p>
<blockquote>
<p>Taken from "3.1 - Slim (Logic-less) models" in <a target="_blank" href="https://solidbook.io">solidbook.io</a>.</p>
</blockquote>
<p>If there's something I've learned so far in my journey going beyond MVC, it's that <strong>there is a construct for everything</strong>.</p>
<p>For each of those things that MVC fails to address, there exist other <strong>enterprise patterns</strong> to solve them. For example:</p>
<ul>
<li><strong><a target="_blank" href="https://khalilstemmler.com/articles/typescript-domain-driven-design/entities/">Entities</a></strong> describe models that have an identity.</li>
<li><strong><a target="_blank" href="https://khalilstemmler.com/articles/typescript-value-object/">Value Objects</a></strong> are models that have no identity, and can be used in order to encapsulate validation logic.</li>
<li><strong><a target="_blank" href="https://khalilstemmler.com/articles/typescript-domain-driven-design/chain-business-logic-domain-events/">Domain Events</a></strong> are events that signify some relevant business event occurring, and can be subscribed to from other components.</li>
</ul>
<p>Depending on the architectural style you've chosen, there are going to be a ton of other enterprise patterns for you to learn in order to implement that pattern to it's fullest potential. </p>
<h3 id="heading-integration-patterns">Integration patterns</h3>
<p>Once your application is up and running, as you get more and more users, you might run into performance issues. API calls might take a long time, servers might crash from being overloaded with requests, etc. In order to solve these problems, you might read about integrating things like <strong>message queues</strong> or <strong>caches</strong> in order to improve performance. </p>
<p>This is probably the most challenging stuff: <em>scaling, audits, and performance</em>. </p>
<p>Designing a system for <em>scale</em> can be incredibly challenging. It requires a deep understanding of the limitations of each component within the architecture, and a plan of action for how to mitigate stress on your architecture and continue to serve requests in high-traffic situations.</p>
<p>The need also the need to <em>audit</em> what's going on in your application. Large enterprise companies need to be able to perform audits in order to identify potential security issues, understand how users are using their applications, and  have a log of everything that's ever happened.</p>
<p>This can be challenging to implement, but common architectures end up looking <strong>event-based</strong> and build upon a wide range of software and system design concepts, principles, and practices like Event Storming, DDD, CQRS (command query response segregation), and Event Sourcing.</p>
<hr>
<p>I hope that was useful to you!</p>
<p>Let me know if you have any suggestions or questions.</p>
<p>Cheers!</p>
<p><a target="_blank" href="https://github.com/stemmlerjs/software-design-and-architecture-roadmap">Fork it on GitHub</a></p>
<p><a target="_blank" href="https://solidbook.io">Read the book on software design &amp; architecture</a></p>
<p><a target="_blank" href="https://khalilstemmler.com/articles/software-design-architecture/full-stack-software-design/">Read the write-up</a></p>
<hr>
<blockquote>
<p><a target="_blank" href="https://khalilstemmler.com">khalilstemmler.com</a> - I teach Advanced TypeScript &amp; Node.js best practices for large-scale applications and how to write flexible, maintainable software.</p>
</blockquote>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ An Introduction to High Availability Computing: Concepts and Theory ]]>
                </title>
                <description>
                    <![CDATA[ Let’s focus more on some of the larger architectural principles of cluster management than on any single technology solution.  We get to see some actual implementations later in the book - and you can learn a lot about how this works on Amazon’s AWS ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/high-availability-concepts-and-theory/</link>
                <guid isPermaLink="false">66b995e022379234769e45ef</guid>
                
                    <category>
                        <![CDATA[ architecture ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Computer Science ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Devops ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ David Clinton ]]>
                </dc:creator>
                <pubDate>Tue, 23 Jul 2019 14:15:00 +0000</pubDate>
                <media:content url="https://cdn-media-2.freecodecamp.org/w1280/5f9ca146740569d1a4ca4db1.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Let’s focus more on some of the larger architectural principles of cluster management than on any single technology solution. </p>
<p>We get to see some actual implementations later in the book - and you can learn a lot about how this works on Amazon’s AWS in my <a target="_blank" href="https://livebook.manning.com/#!/book/learn-amazon-web-services-in-a-month-of-lunches/chapter-14">Learn Amazon Web Services in a Month of Lunches book</a> from Manning. But for now, let’s first make sure we’re comfortable with the basics.</p>
<p>Running server operations using clusters of either physical or virtual computers is all about improving both reliability and performance over and above what you could expect from a single, high-powered server. You add reliability by avoiding hanging your entire infrastructure on a single point of failure (i.e., a single server). And you can increase performance through the ability to very quickly add computing power and capacity by scaling up and out.</p>
<p>This might happen through intelligently spreading your workloads among diverse geographic and demand environments (load balancing), providing<br>backup servers that can be quickly brought into service in the event a working node fails (failover), optimizing the way your data tier is deployed, or allowing for fault tolerance through loosely coupled architectures.</p>
<p>We’ll get to all that. First, though, here are some basic definitions:</p>
<p><strong>Node</strong>: A single machine (either physical or virtual) running server operations independently on its own operating system. Since any single node can fail, meeting availability goals requires that multiple nodes operate as part of a cluster.</p>
<p><strong>Cluster</strong>: Two or more server nodes running in coordination with each other to complete individual tasks as part of a larger service, where mutual awareness allows one or more nodes to compensate for the loss of another.</p>
<p><strong>Server failure</strong>: The inability of a server node to respond adequately to client requests. This could be due to a complete crash, connectivity problems, or because it has been overwhelmed by high demand.</p>
<p><strong>Failover</strong>: The way a cluster tries to accommodate the needs of clients orphaned by the failure of a single server node by launching or redirecting other nodes to fill a service gap.</p>
<p><strong>Failback</strong>: The restoration of responsibilities to a server node as it recovers from a failure.</p>
<p><strong>Replication</strong>: The creation of copies of critical data stores to permit reliable synchronous access from multiple server nodes or clients and to ensure they will survive disasters. Replication is also used to enable reliable load balancing.</p>
<p><strong>Redundancy</strong>: The provisioning of multiple identical physical or virtual server nodes of which any one can adopt the orphaned clients of another one that fails.</p>
<p><strong>Split brain</strong>: An error state in which network communication between nodes or shared storage has somehow broken down and multiple individual nodes, each believing it’s the only node still active, continue to access and update a common data source. While this doesn’t impact shared-nothing designs, it can lead to client errors and data corruption within shared clusters.</p>
<p><strong>Fencing</strong>: To prevent split brain, the stonithd daemon can be configured to automatically shut down a malfunctioning node or to impose a virtual fence between it and the data resources of the rest of a cluster. As long as there is a chance that the node could still be active, but is not properly coordinating with the rest of the cluster, it will remain behind the fence. Stonith stands for “Shoot the other node in the head”. Really.</p>
<p><strong>Quorum</strong>: You can configure fencing (or forced shutdown) to be imposed on nodes that have fallen out of contact with each other or with some shared resource. Quorum is often defined as more than half of all the nodes on the total cluster. Using such defined configurations, you avoid having two subclusters of nodes, each believing the other to be malfunctioning, attempting to knock the other one out.</p>
<p><strong>Disaster Recover</strong>y: Your infrastructure can hardly be considered highly available if you’ve got no automated backup system in place along with an integrated and tested disaster recovery plan. Your plan will need to account for the redeployment of each of the servers in your cluster.</p>
<h2 id="heading-activepassive-cluster">Active/Passive Cluster</h2>
<p>The idea behind service failover is that the sudden loss of any one node in a service cluster would quickly be made up by another node taking its place. For this to work, the IP address is automatically moved to the standby node in the event of a failover. Alternatively, network routing tools like load balancers can be used to redirect traffic away from failed nodes. The precise way failover happens depends on the way you have configured your nodes.</p>
<p>Only one node will initially be configured to serve clients, and will continue to do so alone until it somehow fails. The responsibility for existing and new clients will then shift (i.e., “failover”) to the passive — or backup — node that until now has been kept passively in reserve. Applying the model to multiple servers or server room components (like power supplies), n+1 redundancy provides just enough resources for the current demand plus one more unit to cover for a failure.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*f3FAK-0sBhz347VYjQUsEQ.png" alt="Image" width="1280" height="720" loading="lazy"></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*MXXBRytPbze9nmY0RH_8Ag.png" alt="Image" width="1280" height="720" loading="lazy"></p>
<h2 id="heading-activeactive-cluster">Active/Active Cluster</h2>
<p>A cluster using an active/active design will have two or more identically configured nodes independently serving clients.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*BAZtz_iDmGIj2hy-MvuUPg.png" alt="Image" width="1280" height="720" loading="lazy"></p>
<p>Should one node fail, its clients will automatically connect with the second node and, as far as resources permit, receive full resource access.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*g5Q9d7nhz8cghuLT1l2IzA.png" alt="Image" width="1280" height="720" loading="lazy"></p>
<p>Once the first node recovers or is replaced, clients will once again be split between both server nodes.</p>
<p>The primary advantage of running active/active clusters lies in the ability to efficiently balance a workload between nodes and even networks. The load balancer — which directs all requests from clients to available servers — is configured to monitor node and network activity and use some predetermined algorithm to route traffic to those nodes best able to handle it. Routing policies might follow a round-robin pattern, where client requests are simply alternated between available nodes, or by a preset weight where one node is favored over another by some ratio.</p>
<p>Having a passive node acting as a stand-by replacement for its partner in an active/passive cluster configuration provides significant built-in redundancy. If your operation absolutely requires uninterrupted service and seamless failover transitions, then some variation of an active/passive architecture should be your goal.</p>
<h2 id="heading-shared-nothing-vs-shared-disk-clusters">Shared-Nothing vs. Shared-Disk Clusters</h2>
<p>One of the guiding principles of distributed computing is to avoid having your operation rely on any single point of failure. That is, every resource should be either actively replicated (redundant) or independently replaceable (failover), and there should be no single element whose failure could bring down your whole service.</p>
<p>Now, imagine that you’re running a few dozen nodes that all rely on a single database server for their function. Even though the failure of any number of the nodes will not affect the continued health of those nodes that remain, should the database go down, the entire cluster would become useless. Nodes in a shared-nothing cluster, however, will (usually) maintain their own databases so that — assuming they’re being properly synced and configured for ongoing transaction safety — no external failure will impact them.</p>
<p>This will have a more significant impact on a load balanced cluster, as each load balanced node has a constant and critical need for simultaneous access to the data. The passive node on a simple failover system, however, might be able to survive some time without access.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*79d-yp6C8tdPJ5Fiu14Wkg.png" alt="Image" width="1280" height="720" loading="lazy"></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*C34EBTHibYVGWLZriOZtdQ.png" alt="Image" width="1280" height="720" loading="lazy"></p>
<p>While such a setup might slow down the way the cluster responds to some requests — partly because fears of split-brain failures might require periodic fencing through stonith — the trade off can be justified for mission critical deployments where reliability is the primary consideration.</p>
<h2 id="heading-availability">Availability</h2>
<p>When designing your cluster, you’ll need to have a pretty good sense of just how tolerant you can be of failure. Or, in other words, given the needs of the people or machines consuming your services, how long can a service disruption last before the mob comes pouring through your front gates with pitch forks and flaming torches. It’s important to know this, because the amount of redundancy you build into your design will have an enormous impact on the down-times you will eventually face.</p>
<p>Obviously, the system you build for a service that can go down for a weekend without anyone noticing will be very different from an e-commerce site whose customers expect 24/7 access. At the very least, you should generally aim for an availability average of at least 99% — with some operations requiring significantly higher real-world results. 99% up time would translate to a loss of less than a total of four days out of every year.</p>
<p>There is a relatively simple formula you can use to build a useful estimate of Availability (A). The idea is to divide the Mean Time Before Failure by the Mean Time Before Failure plus Mean Time To Repair.</p>
<p>A = MTBF / (MTBF + MTTR)</p>
<p>The closer the value of A comes to 1, the more highly available your cluster will be. To obtain a realistic value for MTBF, you’ll probably need to spend time exposing a real system to some serious punishment, and watching it carefully for software, hardware, and networking failures. I suppose you could also consult the published life cycle metrics of hardware vendors or large-scale consumers like Backblaze to get an idea of how long heavily-used hardware can be expected to last.</p>
<p>The MTTR will be a product of the time it takes your cluster to replace the functionality of a server node that’s failed (a process that’s similar to, though not identical with, disaster recovery — which focuses on quickly replacing failed hardware and connectivity). Ideally, that would be a value as close to zero seconds as possible.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*qGnfvJNjSyUwjFQl0q5OhQ.png" alt="Image" width="566" height="294" loading="lazy">
<em>Server Availability</em></p>
<p>The problem is that, in the real world, there are usually far too many unknown variables for this formula to be truly accurate, as nodes running different software configurations and built with hardware of varying profiles and ages will have a wide range of life expectancies. Nevertheless, it can be a good tool to help you identify the cluster design that’s best for your project.</p>
<p>With that information, you can easily generate an estimate of how much overall downtime your service will likely in the course of an entire year.</p>
<p>A related consideration, if you’re deploying your resources on a third-party platform provider like VMWare or Amazon Web Services, is the provider’s Service Level Agreement (SLA). Amazon’s EC2, for instance, guarantees that their compute instances and block store storage devices will deliver a Monthly Uptime Percentage of at least 99.95% — which is less than five hours’ down time per year. AWS will issue credits for months in which they missed their targets — though not nearly enough to compensate for the total business costs of your downtime. With that information, you can arrange for a level of service redundancy that’s suitable for your unique needs.</p>
<p>Naturally, as a service provider to your own customers, you may need to publish your own SLA based on your MTBF and MTTR estimates.</p>
<h2 id="heading-session-handling">Session Handling</h2>
<p>For any server-client relationship, the data generated by stateful HTTP sessions needs to be saved in a way that makes it available for future interactions. Cluster architectures can introduce serious complexity into these relationships, as the specific server a client or user interacts with might change between one step and the next.</p>
<p>To illustrate, imagine you’re logged onto Amazon.com, browsing through their books on LPIC training, and periodically adding an item to your cart (hopefully, more copies of this book). By the time you’re ready to enter your payment information and check out, however, the server you used to browse may no longer even exist. How will your current server know which books you decided to purchase?</p>
<p>I don’t know exactly how Amazon handles this<a target="_blank" href="https://www.manning.com/books/learn-amazon-web-services-in-a-month-of-lunches?a_aid=bootstrap-it&amp;a_bid=1c1b5e27">,</a> but the problem is often addressed through a data replication tool like memcached running on an<br>external node (or nodes). The goal is to provide constant access to a reliable and consistent data source to any node that might need it.</p>
<p><em>This article is adapted from “</em><a target="_blank" href="https://www.amazon.com/gp/product/B06XTZ4YWQ/ref=as_li_tl?ie=UTF8&amp;camp=1789&amp;creative=9325&amp;creativeASIN=B06XTZ4YWQ&amp;linkCode=as2&amp;tag=projemun-20&amp;linkId=fa7577d96ed91ffe111b08665bcb53f9"><em>Teach Yourself Linux Virtualization and High Availability: prepare for the LPIC-3 304 certification exam</em></a><em>”. Check out my</em> <a target="_blank" href="https://bootstrap-it.com/"><em>other books on AWS and Linux administration</em></a><em>, including</em> <a target="_blank" href="https://www.manning.com/books/linux-in-action?a_aid=bootstrap-it&amp;a_bid=4ca15fc9"><em>Linux in Action</em></a> <em>and</em> <a target="_blank" href="https://www.manning.com/livevideo/linux-in-motion?a_aid=bootstrap-it&amp;a_bid=0c56986f&amp;chan=motion1"><em>Linux in Motion</em></a> <em>— a hybrid course made up of more than two hours of video and around 40% of the text of Linux in Action.</em></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ What is Serverless Architecture? What are its Pros and Cons? ]]>
                </title>
                <description>
                    <![CDATA[ By Faizan Bashir Serverless, the new buzzword in town has been gaining a lot of attention from the pros and the rookies in the tech industry. Partly due to the manner in which cloud vendors like AWS have hyped the architecture, from conferences to m... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/what-is-serverless-architecture-what-are-its-pros-and-cons/</link>
                <guid isPermaLink="false">66d45ef7bc9760a197a103c3</guid>
                
                    <category>
                        <![CDATA[ architecture ]]>
                    </category>
                
                    <category>
                        <![CDATA[ lambda ]]>
                    </category>
                
                    <category>
                        <![CDATA[ serverless ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Fri, 05 Jul 2019 18:43:27 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2019/07/1_16x1_xEclXT4MB0FN_xr2g.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Faizan Bashir</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*16x1_xEclXT4MB0FN_xr2g.jpeg" alt="Image" width="1920" height="1080" loading="lazy"></p>
<p>Serverless, the new buzzword in town has been gaining a lot of attention from the pros and the rookies in the tech industry. Partly due to the manner in which cloud vendors like AWS have hyped the architecture, from conferences to meetups to blog posts to almost everywhere. But serverless is not just about the hype, it promises the possibility of ideal business implementations which sounds quite pleasant to the ears and probably light on the budget as well.</p>
<blockquote>
<p><em>“Focus on your</em> <strong><em>application</em></strong>, not the <strong>infrastructure</strong>”</p>
</blockquote>
<p>Sounds relieving though, knowing a lot of your daylight hours go into implementing, maintaining, debugging, and monitoring the infrastructure. With all of that infrastructure heavy lifting out of the way, we really can focus on the business goals our applications serve. A lot of productive efforts could be channeled in the right direction, where they were meant to be ideally. Maybe it sounds too good to be true, but this is the way things should have been. At least for those of you who cant afford to spend a lot of time caught up in the web of intricacies in modern complex infrastructure.</p>
<p>Expectations apart, Serverless is really breaking ground in its path to disrupt your server infrastructure. Serverless is already used in production by companies like Netflix, Reuters, AOL, and Telenor. Industry-wide adoption is constantly increasing. Serverless is all set to take up its own place, but don’t expect Serverless to conquer your infrastructure completely. There will be use cases where serverless might prove to be the wrong choice.</p>
<hr>
<h3 id="heading-so-what-is-serverless">So, What is Serverless?</h3>
<p>Serverless is a cloud computing execution model where the cloud provider dynamically manages the allocation and provisioning of servers. A serverless application runs in stateless compute containers that are event-triggered, ephemeral (may last for one invocation), and fully managed by the cloud provider. Pricing is based on the number of executions rather than pre-purchased compute capacity, isn’t it the ideal framework for that project you have been planning since a long time? Well, go ahead do it.</p>
<blockquote>
<p><em>Serverless applications are event-driven cloud-based systems where application development rely solely on a combination of</em> <strong><em>third-party services, client-side logic</em></strong> and cloud-hosted remote procedure calls <strong>(Functions as a Service)</strong>.</p>
</blockquote>
<p>Most of the cloud providers have invested heavily in serverless and thats a lot of money; with the given massive promotion and realistic offering you can safely assume serverless to be one of the most used cloud services in upcoming years. Here are some of the currently available cloud services:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*t4O4UXpdG68MQboNKC6bBw.jpeg" alt="Image" width="638" height="359" loading="lazy"></p>
<p><em>Source:</em> <a target="_blank" href="https://www.slideshare.net/loige/building-a-serverless-company-with-nodejs-react-and-the-serverless-framework-jsday-2017-verona"><em>https://www.slideshare.net/loige/building-a-serverless-company-with-nodejs-react-and-the-serverless-framework-jsday-2017-verona</em></a></p>
<ul>
<li><p><a target="_blank" href="https://aws.amazon.com/lambda/"><strong>AWS Lambda</strong></a></p>
</li>
<li><p><a target="_blank" href="https://cloud.google.com/functions/"><strong>Google Cloud Functions</strong></a></p>
</li>
<li><p><a target="_blank" href="https://azure.microsoft.com/en-us/services/functions/"><strong>Azure Functions</strong></a></p>
</li>
<li><p><a target="_blank" href="https://www.ibm.com/cloud-computing/bluemix/openwhisk"><strong>IBM OpenWhisk</strong></a></p>
</li>
<li><p><a target="_blank" href="https://www.alibabacloud.com/product/function-compute"><strong>Alibaba Function Compute</strong></a></p>
</li>
<li><p><a target="_blank" href="http://open.iron.io/"><strong>Iron Functions</strong></a></p>
</li>
<li><p><a target="_blank" href="https://webtask.io/"><strong>Auth0 Webtask</strong></a></p>
</li>
<li><p><a target="_blank" href="https://fnproject.io/"><strong>Oracle Fn Project</strong></a></p>
</li>
<li><p><a target="_blank" href="https://kubeless.io/"><strong>Kubeless</strong></a></p>
</li>
</ul>
<hr>
<h3 id="heading-traditional-vs-serverless-architecture">Traditional vs. Serverless Architecture</h3>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*x_v5NRC3TTMt1MaYl1gMUg.jpeg" alt="Image" width="1024" height="768" loading="lazy"></p>
<p><em>Source:</em> <a target="_blank" href="https://www.gocd.org/2017/06/26/serverless-architecture-continuous-delivery/"><em>https://www.gocd.org/2017/06/26/serverless-architecture-continuous-delivery/</em></a></p>
<p>For years your applications have run on servers which you had to patch, update, and continuously look after late nights and early mornings due to all the unimaginable errors that broke your production. As long as you managed them, the whole responsibility of their proper functioning was on you. Serverless tends to be unlike the aforementioned, you no longer need to worry about the underlying servers. Reason being, they are not managed by you anymore and with management out of the picture the responsibility falls on the Cloud vendors. But regardless the cool features of Serverless in some cases, the traditional architecture outshines it.</p>
<h4 id="heading-pricing">Pricing</h4>
<p>One of the major advantages of using Serverless is reduced cost, for years the cost of provisioning servers and maintaining that 24x7 server team which blew a hole in your pocket is gone. The cost model of Serverless is execution-based: you’re charged for the number of executions. You’re allotted a certain number of seconds of use that varies with the amount of memory you require. Likewise, the price per MS (millisecond) varies with the amount of memory you require. Obviously, shorter running functions are more adaptable to this model with a peak execution time of 300-second to 15-minutes for most Cloud vendors.</p>
<p><em>The winner here is Serverless Architecture.</em></p>
<h4 id="heading-networking">Networking</h4>
<p>The downside is that Serverless functions are accessed only as private APIs. To access these you must set up an API Gateway. This doesn’t have an impact on your pricing or process, but it means you cannot directly access them through the usual IP, snap!</p>
<p><em>The winner here is Traditional Architecture.</em></p>
<h4 id="heading-3rd-party-dependencies">3rd Party Dependencies</h4>
<p>Most, if not all of your projects have external dependencies, they rely on libraries that are not built into the language or framework you use. You often use libraries with functionality that includes cryptography, image processing, etc., these libraries can be pretty heavy. Without system-level access, you must package these dependencies into the application itself.</p>
<blockquote>
<p><em>Reinventing the wheel isn’t always a good idea.</em></p>
</blockquote>
<p><em>The winner here is based on the context. For simple applications with few dependencies, Serverless is the winner; for anything more complex, Traditional Architecture is the winner.</em></p>
<h4 id="heading-environments">Environments</h4>
<p>Setting up different environments for Serverless is as easy as setting up a single environment. Given that it’s pay per execution, this is a large improvement over traditional servers, you no longer need to set up dev, staging, and production machines. Eventually you’d lose count of all the environments, at some point.</p>
<p><em>The winner here is Serverless Architecture.</em></p>
<h4 id="heading-timeout">Timeout</h4>
<p>With Serverless computing, there’s a <a target="_blank" href="https://aws.amazon.com/about-aws/whats-new/2018/10/aws-lambda-supports-functions-that-can-run-up-to-15-minutes/">hard 15-minute timeout limit for AWS Lambda</a>. Too complex or long-running functions aren’t good for Serverless, but having a hard timeout makes it impossible to perform certain tasks. A hard limit on this time makes Serverless unusable for applications that have variable execution times, and for certain services which require information from an external source. This is likely to change in the future.</p>
<p><em>The clear winner here is Traditional Architecture.</em></p>
<h4 id="heading-scale">Scale</h4>
<p>Scaling process for Serverless is automatic and seamless, but there is a lack of control or entire absence of control. While automatic scaling is great, it’s difficult not to be able to address and mitigate errors related to new Serverless instances.</p>
<p><em>It’s a tie between Serverless and Traditional Architecture.</em></p>
<hr>
<h3 id="heading-functions-as-a-service-faas">Functions as a Service (FaaS)</h3>
<p>FaaS is an implementation of Serverless architectures where engineers can deploy an individual function or a piece of business logic. They start within milliseconds (~100ms for AWS Lambda) and process individual requests within a 300-second to 15-minute timeout imposed by most cloud vendors.</p>
<h4 id="heading-principles-of-faas"><strong>Principles of FaaS:</strong></h4>
<ul>
<li><p>Complete management of servers</p>
</li>
<li><p>Invocation based billing</p>
</li>
<li><p>Event-driven and instantaneously scalable</p>
</li>
</ul>
<h3 id="heading-key-properties-of-faas">Key properties of FaaS:</h3>
<h4 id="heading-independent-server-side-logical-functions">Independent, server-side, logical functions</h4>
<p>FaaS are similar to the functions you’re used to writing in programming languages, small, separate, units of logic that take input arguments, operate on the input and return the result.</p>
<h4 id="heading-stateless">Stateless</h4>
<p>With Serverless, everything is stateless, you can’t save a file to disk on one execution of your function and expect it to be there at the next. Any two invocations of the same function could run on completely different containers under the hood.</p>
<h4 id="heading-ephemeral">Ephemeral</h4>
<p>FaaS are designed to spin up quickly, do their work and then shut down again. They do not linger unused. As long as the task is performed the underlying containers are scrapped.</p>
<h4 id="heading-event-triggered">Event-triggered</h4>
<p>Although functions can be invoked directly, yet they are usually triggered by events from other cloud services such as HTTP requests, new database entries or inbound message notifications. FaaS are often used and thought of as the glue between services in a cloud environment.</p>
<h4 id="heading-scalable-by-default">Scalable by default</h4>
<p>With stateless functions multiple containers can be initialised, allowing as many functions to be run (in parallel, if necessary) as needed to continually service all incoming requests.</p>
<h4 id="heading-fully-managed-by-a-cloud-vendor">Fully managed by a Cloud vendor</h4>
<p>AWS Lambda, Azure Functions, IBM OpenWhisk and Google Cloud Functions are most well-known FaaS solutions available. Each offering typically supports a range of languages and runtimes e.g. Node.js, Python, .NET Core, Java.</p>
<hr>
<h3 id="heading-the-serverless-app">The Serverless App</h3>
<p>A Serverless solution consists of a web server, Lambda functions (FaaS), security token service (STS), user authentication and database.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*TIrjN7EjLUVJmJ6YvHR7Dg.png" alt="Image" width="1376" height="704" loading="lazy"></p>
<p><em>Source:</em> <a target="_blank" href="http://blog.tonyfendall.com/2015/12/serverless-architectures-using-aws-lambda/"><em>http://blog.tonyfendall.com/2015/12/serverless-architectures-using-aws-lambda/</em></a></p>
<ul>
<li><p><strong>Client Application</strong> — The UI of your application is rendered client side in Modern Frontend Javascript App which allows us to use a simple, static web server.</p>
</li>
<li><p><strong>Web Server</strong> — Amazon S3 provides a robust and simple web server. All of the static HTML, CSS and JS files for our application can be served from S3.</p>
</li>
<li><p><strong>Lambda functions (FaaS)</strong> — They are the key enablers in Serverless architecture. Some popular examples of FaaS are AWS Lambda, Google Cloud Functions and Microsoft Azure Functions. AWS Lambda is used in this framework. The application services for logging in and accessing data will be built as Lambda functions. These functions will read and write from your database and provide JSON responses.</p>
</li>
<li><p><strong>Security Token Service (STS)</strong> — generates temporary AWS credentials (API key and secret key) for users of the application. These temporary credentials are used by the client application to invoke the AWS API (and thus invoke Lambda).</p>
</li>
<li><p><strong>User Authentication</strong> — AWS Cognito is an identity service which is integrated with AWS Lambda. With Amazon Cognito, you can easily add user sign-up and sign-in to your mobile and web apps. It also has the options to authenticate users through social identity providers such as Facebook, Twitter or Amazon, with SAML identity solutions, or using your own identity system.</p>
</li>
<li><p><strong>Database</strong> — AWS DynamoDB provides a fully managed NoSQL database. DynamoDB is not essential for a serverless application but is used as an example here.</p>
</li>
</ul>
<hr>
<h3 id="heading-benefits-of-serverless-architecture">Benefits of Serverless Architecture</h3>
<h4 id="heading-from-business-perspective"><strong>From business perspective</strong></h4>
<ol>
<li><p>The cost incurred by a serverless application is based on the number of function executions, measured in milliseconds instead of hours.</p>
</li>
<li><p>Process agility: Smaller deployable units result in faster delivery of features to the market, increasing the ability to adapt to change.</p>
</li>
<li><p>Cost of hiring backend infrastructure engineers goes down.</p>
</li>
<li><p>Reduced operational costs</p>
</li>
</ol>
<h4 id="heading-from-developer-perspective"><strong>From developer perspective</strong></h4>
<ol>
<li><p>Reduced liability, no backend infrastructure to be responsible for.</p>
</li>
<li><p>Zero system administration.</p>
</li>
<li><p>Easier operational management.</p>
</li>
<li><p>Fosters adoption of Nanoservices, Microservices, SOA Principles.</p>
</li>
<li><p>Faster set up.</p>
</li>
<li><p>Scalable, no need to worry about the number of concurrent requests.</p>
</li>
<li><p>Monitoring out of the box.</p>
</li>
<li><p>Fosters innovation.</p>
</li>
</ol>
<h4 id="heading-from-user-perspective"><strong>From user perspective</strong></h4>
<ol>
<li><p>If businesses are using that competitive edge to ship features faster, then customers are receiving new features quicker than before.</p>
</li>
<li><p>It is possible that users can more easily provide their own storage backend(i.e Dropbox, Google Drive).</p>
</li>
<li><p>It’s more likely that these kinds of apps may offer client-side caching, which provides a better offline experience.</p>
</li>
</ol>
<hr>
<h3 id="heading-drawbacks-of-serverless-architecture">Drawbacks of Serverless Architecture</h3>
<h4 id="heading-from-business-perspective-1"><strong>From business perspective</strong></h4>
<ol>
<li><p>Reduced overall control.</p>
</li>
<li><p>Vendor lock-in requires more trust for a third-party provider.</p>
</li>
<li><p>Additional exposure to risk requires more trust for a third party provider.</p>
</li>
<li><p>Security risk.</p>
</li>
<li><p>Disaster recovery risk</p>
</li>
<li><p>Cost is unpredictable because the number of executions is not predefined</p>
</li>
<li><p>All of these drawbacks can be mitigated with open-source alternatives but at the expense of cost benefits mentioned previously</p>
</li>
</ol>
<h4 id="heading-from-developer-perspective-1"><strong>From developer perspective</strong></h4>
<ol>
<li><p>Immature technology results in component fragmentation, unclear best-practices.</p>
</li>
<li><p>Architectural complexity.</p>
</li>
<li><p>The discipline required against function sprawl.</p>
</li>
<li><p>Multi-tenancy means it’s technically possible that neighbour functions could hog the system resources behind the scenes.</p>
</li>
<li><p>Testing locally becomes tricky.</p>
</li>
<li><p>Significant restrictions on the local state.</p>
</li>
<li><p>Execution duration is capped.</p>
</li>
<li><p>Lack of operational tools</p>
</li>
</ol>
<h4 id="heading-from-user-perspective-1"><strong>From user perspective</strong></h4>
<ol>
<li>Unless architected correctly, an app could provide a poor user experience as a result of increased request latency.</li>
</ol>
<hr>
<h3 id="heading-serverless-frameworks">Serverless Frameworks</h3>
<p><em>Source: https//serverless.com</em></p>
<p>Serverless platforms need infrastructures where they can be executed, provider agnostic frameworks provide a platform agnostic way to define and deploy Serverless code on various cloud platforms or commercial services.</p>
<ul>
<li><p><a target="_blank" href="https://serverless.com/">Serverless Framework</a> (Javascript, Python, Golang)</p>
</li>
<li><p><a target="_blank" href="http://apex.run/">Apex</a> (Javascript)</p>
</li>
<li><p><a target="_blank" href="https://claudiajs.com/">ClaudiaJS</a> (Javascript)</p>
</li>
<li><p><a target="_blank" href="https://gosparta.io/">Sparta</a> (Golang)</p>
</li>
<li><p><a target="_blank" href="https://github.com/jorgebastida/gordon">Gordon</a> (Javascript)</p>
</li>
<li><p><a target="_blank" href="https://www.zappa.io/">Zappa</a> (Python)</p>
</li>
<li><p><a target="_blank" href="https://github.com/apex/up">Up</a> (Javascript, Python, Golang, Crystal)</p>
</li>
</ul>
<hr>
<h3 id="heading-summary">Summary</h3>
<p>Serverless architecture is certainly very exciting, but it comes with a bunch of limitations. As the validity and success of architectures depend on the business requirements and by no means solely on technology. In the same way, Serverless can shine when used in proper place.</p>
<p>Take a look at the awesomeness that is Serverless, it's time to take a peek at what Serverless looks from the inside. Here are few links to get you started on your Serverless journey.</p>
<p><a target="_blank" href="https://github.com/serverless/examples"><strong>serverless/examples</strong></a><br><a target="_blank" href="https://github.com/serverless/examples">_Serverless Examples - A collection of boilerplates and examples of serverless architectures built with the Serverless…_github.com</a></p>
<p><a target="_blank" href="https://github.com/anaibol/awesome-serverless"><strong>anaibol/awesome-serverless</strong></a><br><a target="_blank" href="https://github.com/anaibol/awesome-serverless">_awesome-serverless - :cloud: A curated list of awesome services, solutions and resources for serverless / nobackend…_github.com</a></p>
<p><a target="_blank" href="https://hackernoon.com/building-serverless-contact-form-for-static-websites-b0e622d5a035"><strong>Building Serverless Contact Form For Static Websites</strong></a><br><a target="_blank" href="https://hackernoon.com/building-serverless-contact-form-for-static-websites-b0e622d5a035">_Handling static forms with AWS serverless lambda functions_hackernoon.com</a></p>
<p>I hope this article helped in the understanding of Serverless Computing. I’d love to hear about how you use Serverless in your projects. Share the knowledge, help it reach more people.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ An in-depth introduction to SQOOP architecture ]]>
                </title>
                <description>
                    <![CDATA[ By Jayvardhan Reddy Apache Sqoop is a data ingestion tool designed for efficiently transferring bulk data between Apache Hadoop and structured data-stores such as relational databases, and vice-versa. _Image Credits: [hdfstutorial.com](https://www.h... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/an-in-depth-introduction-to-sqoop-architecture-ad4ae0532583/</link>
                <guid isPermaLink="false">66c343e4ccd54aa295e92c8a</guid>
                
                    <category>
                        <![CDATA[ architecture ]]>
                    </category>
                
                    <category>
                        <![CDATA[ big data ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Data Science ]]>
                    </category>
                
                    <category>
                        <![CDATA[ hadoop ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technology ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 26 Feb 2019 17:53:46 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*3aWPwVLlbZ8sq4aboE_CQw.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Jayvardhan Reddy</p>
<p><strong>Apache Sqoop</strong> is a data ingestion tool designed for efficiently transferring bulk data between Apache Hadoop and structured data-stores such as relational databases, and vice-versa.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/yA5Wt8JEHKyIDA-bK2ehlgYGN03XXPgKFmdz" alt="Image" width="585" height="271" loading="lazy">
_Image Credits: [hdfstutorial.com](https://www.hdfstutorial.com/sqoop-architecture/" rel="noopener" target="<em>blank" title=")</em></p>
<p>As part of this blog, I will be explaining how the architecture works on executing a Sqoop command. I’ll cover details such as the jar generation via Codegen, execution of MapReduce job, and the various stages involved in running a Sqoop import/export command.</p>
<h3 id="heading-codegen"><strong>Codegen</strong></h3>
<p>Understanding Codegen is essential, as internally this converts our Sqoop job into a jar which consists of several Java classes such as POJO, ORM, and a class that implements DBWritable, extending SqoopRecord to read and write the data from relational databases to Hadoop &amp; vice-versa.</p>
<p>You can create a Codegen explicitly as shown below to check the classes present as part of the jar.</p>
<pre><code>sqoop codegen \   -- connect jdbc:mysql:<span class="hljs-comment">//ms.jayReddy.com:3306/retail_db \   -- username retail_user \   -- password ******* \   -- table products</span>
</code></pre><p>The output jar will be written in your local file system. You will get a Jar file, Java file and java files which are compiled into .class files:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/9584V87MKrbpriG-qjgfkRmU95O4DqMWBMpw" alt="Image" width="800" height="146" loading="lazy"></p>
<p>Let us see a snippet of the code that will be generated.</p>
<p>ORM class for table ‘products’ // Object-relational modal generated for mapping:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/R-YKp7vBHJyG0U9fkHmUrbDnie-O2-3G8PwV" alt="Image" width="800" height="229" loading="lazy"></p>
<p>Setter &amp; Getter methods to get values:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/do50-AIfmsBnWa0UmDElJu8lfJMl0lgATWtk" alt="Image" width="734" height="196" loading="lazy"></p>
<p>Internally it uses JDBC prepared statements to write to Hadoop and ResultSet to read data from Hadoop.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/dp1Oud1aHWZ6zPFRmDhTf5p4KUuPrYIUg4K6" alt="Image" width="800" height="251" loading="lazy"></p>
<h3 id="heading-sqoop-import"><strong>Sqoop Import</strong></h3>
<p>It is used to import data from traditional relational databases into Hadoop.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1fuDCRMH99ZB3HA496qQycCcGQFzs7c6kdNl" alt="Image" width="535" height="346" loading="lazy">
_Image Credits: [dummies.com](https://www.dummies.com/programming/big-data/hadoop/hadoop-for-dummies-cheat-sheet/" rel="noopener" target="<em>blank" title=")</em></p>
<p>Let’s see a sample snippet for the same.</p>
<pre><code>sqoop <span class="hljs-keyword">import</span> \   -- connect jdbc:mysql:<span class="hljs-comment">//ms.jayReddy.com:3306/retail_db \   -- username retail_user \   -- password ******* \   -- table products \   -- warehouse-dir /user/jvanchir/sqoop_prac/import_table_dir \   -- delete-target-dir</span>
</code></pre><p>The following steps take place internally during the execution of sqoop.</p>
<p><strong>Step 1</strong>: Read data from MySQL in streaming fashion. It does various operations before writing the data into HDFS.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/FSvnl854UDyo8C9QKIOO0aMLNBw5uWed-KEJ" alt="Image" width="687" height="24" loading="lazy"></p>
<p>As part of this process, it will first generate code (typical Map reduce code) which is nothing but Java code. Using this Java code it will try to import.</p>
<ul>
<li>Generate the code. (Hadoop MR)</li>
<li>Compile the code and generate the Jar file.</li>
<li>Submit the Jar file and perform the import operations</li>
</ul>
<p>During the import, it has to make certain decisions as to how to divide the data into multiple threads so that Sqoop import can be scaled.</p>
<p><strong>Step 2</strong>: Understand the structure of the data and perform CodeGen</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/iw8VSQhwmd4uvmqwN0MxCG15xrFBPGyRZdXy" alt="Image" width="800" height="45" loading="lazy"></p>
<p>Using the above SQL statement, it will fetch one record along with the column names. Using this information, it will extract the metadata information of the columns, datatype etc.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/rEfjXBnXyMjmyvtcIub-cxby3LS31vpFCFyt" alt="Image" width="476" height="418" loading="lazy">
_Image Credits: [cs.tut.fi](http://www.cs.tut.fi/~aaltone3/kurssit/hadoop/Sqoop_pdf.pdf" rel="noopener" target="<em>blank" title=")</em></p>
<p><strong>Step 3</strong>: Create the java file, compile it and generate a jar file</p>
<p>As part of code generation, it needs to understand the structure of the data and it has to apply that object on the incoming data internally to make sure the data is correctly copied onto the target database. Each unique table has one Java file talking about the structure of data.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/IVi4qXeQV0wHLso3jw-YSNt4Qdq1jz5WOSSQ" alt="Image" width="800" height="39" loading="lazy"></p>
<p>This jar file will be injected into Sqoop binaries to apply the structure to incoming data.</p>
<p><strong>Step 4</strong>: Delete the target directory if it already exists.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/PnNCCNdcFYG63ckjOdNQz9sLwHwp-xQhA6mh" alt="Image" width="800" height="22" loading="lazy"></p>
<p><strong>Step 5</strong>: Import the data</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/L0xKeU6eZzzFNXq9GTUizLA9daPHdicLyKcm" alt="Image" width="800" height="60" loading="lazy"></p>
<p>Here, it connects to a resource manager, gets the resource, and starts the application master.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/0k04I6Df7Ox1UGcxyOEqh-WENTYZtboAPfAH" alt="Image" width="719" height="22" loading="lazy"></p>
<p>To perform equal distribution of data among the map tasks, it internally executes a boundary query based on the primary key by default<br> to find the minimum and maximum count of records in the table.<br> Based on the max count, it will divide by the number of mappers and split it amongst each mapper.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/ixpOtqkpYybBmnTLp1o9vsvkG5Z22ybCYWMB" alt="Image" width="800" height="92" loading="lazy"></p>
<p>It uses 4 mappers by default:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/SvulfY8XlKP3-Th9pY7nLI0RBaWZs4spjFWv" alt="Image" width="800" height="284" loading="lazy"></p>
<p>It executes these jobs on different executors as shown below:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/4doX1MPcDsGOirBF0qyTlaEZCUEvZfiCqg1w" alt="Image" width="800" height="140" loading="lazy"></p>
<p>The default number of mappers can be changed by setting the following parameter:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/J4gGRZO4nsjSvBqfH8yopHaCgYyodWutLGLl" alt="Image" width="739" height="26" loading="lazy"></p>
<p>So in our case, it uses 4 threads. Each thread processes mutually exclusive subsets, that is each thread processes different data from the others.</p>
<p>To see the different values, check out the below:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/bRNZNgynB99qUWQVotlG0PCM7UYUYMzatqE1" alt="Image" width="800" height="338" loading="lazy"></p>
<p>Operations that are being performed under each executor nodes:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/Q6V3RYKFJ56mlEPTX5VTPGQqBYWpdlSGBoXW" alt="Image" width="800" height="153" loading="lazy"></p>
<p>In case you perform a Sqooop hive import, one extra step as part of the execution takes place.</p>
<p><strong>Step 6</strong>: Copy data to hive table</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/TRcmgwhHAQy2SutU-R13R53ejFPJ2j2JsB7R" alt="Image" width="800" height="126" loading="lazy"></p>
<h3 id="heading-sqoop-export"><strong>Sqoop Export</strong></h3>
<p>This is used to export data from Hadoop into traditional relational databases.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/s1lKtokuWsuEqmHsb92--czqDaFuQKd8Dvtm" alt="Image" width="800" height="337" loading="lazy">
_Image Credits: [slideshare.net](https://www.slideshare.net/gharriso/from-oracle-to-hadoop-with-sqoop-and-other-tools" rel="noopener" target="<em>blank" title=")</em></p>
<p>Let’s see a sample snippet for the same:</p>
<pre><code>sqoop <span class="hljs-keyword">export</span> \  -- connect jdbc:mysql:<span class="hljs-comment">//ms.jayReddy.com:3306/retail_export \  -- username retail_user \  -- password ******* \  -- table product_sqoop_exp \  -- export-dir /user/jvanchir/sqoop_prac/import_table_dir/products</span>
</code></pre><p>On executing the above command, the execution steps (1–4) similar to Sqoop import take place, but the source data is read from the file system (which is nothing but HDFS). Here it will use boundaries upon block size to divide the data and it is internally taken care by Sqoop.</p>
<p>The processing splits are done as shown below:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/pFCifYgZx8KRMRCVxfJdk7HOigxDTZOX5UQz" alt="Image" width="800" height="67" loading="lazy"></p>
<p>After connecting to the respective database to which the records are to be exported, it will issue a JDBC insert command to read data from HDFS and store it into the database as shown below.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/dWB1TZmEH07zlJ3TOKnVZm1dvzVvbEKOIa5c" alt="Image" width="737" height="26" loading="lazy"></p>
<p>Now that we have seen how Sqoop works internally, you can determine the flow of execution from jar generation to execution of a MapReduce task on the submission of a Sqoop job.</p>
<p><strong>Note<em>:</em></strong> The commands that were executed related to this post are added as part of my <a target="_blank" href="https://github.com/Jayvardhan-Reddy/BigData-Ecosystem-Architecture">GIT</a> account.</p>
<p>Similarly, you can also read more here:</p>
<ul>
<li><a target="_blank" href="https://medium.com/plumbersofdatascience/hive-architecture-in-depth-ba44e8946cbc">Hive Architecture in Depth</a> with <strong>code</strong>.</li>
<li><a target="_blank" href="https://medium.com/plumbersofdatascience/hdfs-architecture-in-depth-1edb822b95fa">HDFS Architecture in Depth</a> with <strong>code</strong>.</li>
</ul>
<p>If you would like too, you can connect with me on LinkedIn - <a target="_blank" href="https://www.linkedin.com/in/jayvardhan-reddy-vanchireddy">Jayvardhan Reddy</a>.</p>
<p>If you enjoyed reading this article, you can click the clap and let others know about it. If you would like me to add anything else, please feel free to leave a response ?</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
