diff --git a/components/helpers/applyFilter.ts b/components/helpers/applyFilter.ts
index a7f3f217d5eb..c2772cce63e1 100644
--- a/components/helpers/applyFilter.ts
+++ b/components/helpers/applyFilter.ts
@@ -137,6 +137,9 @@ export const onFilterApply = (
 
   if (query && Object.keys(query).length >= 1) {
     Object.keys(query).forEach((property) => {
+      if (property === 'page') {
+        return;
+      }
       const res = result.filter((e) => {
         if (!query[property] || e[property] === query[property]) {
           return e[property];
diff --git a/components/navigation/BlogPagination.tsx b/components/navigation/BlogPagination.tsx
new file mode 100644
index 000000000000..6479e105faf5
--- /dev/null
+++ b/components/navigation/BlogPagination.tsx
@@ -0,0 +1,126 @@
+import React, { useEffect, useState } from 'react';
+
+import { ButtonIconPosition } from '@/types/components/buttons/ButtonPropsType';
+
+import Button from '../buttons/Button';
+import IconArrowLeft from '../icons/ArrowLeft';
+import IconArrowRight from '../icons/ArrowRight';
+
+/**
+ * Props for the BlogPagination component
+ * @property {number} blogsPerPage - Number of blogs to display per page
+ * @property {number} totalBlogs - Total number of blogs
+ * @property {function} paginate - Callback function to handle page changes
+ * @property {number} currentPage - Current active page number
+ */
+interface BlogPaginationProps {
+  // eslint-disable-next-line prettier/prettier
+
+  blogsPerPage: number;
+  totalBlogs: number;
+  paginate: (pageNumber: number) => void;
+  currentPage: number;
+}
+
+/**
+ * A pagination component for blog posts that displays page numbers and navigation buttons
+ * @param {BlogPaginationProps} props - The props for the component
+ * @returns {JSX.Element} A navigation element with pagination controls
+ */
+export default function BlogPagination({
+  blogsPerPage,
+  totalBlogs,
+  paginate,
+  currentPage,
+}: BlogPaginationProps) {
+  const totalPages: number = Math.ceil(totalBlogs / blogsPerPage);
+  const pagesToShow: number = 6;
+  const [pageNumbers, setPageNumbers] = useState<(number | string)[]>([]);
+
+  const calculatePageNumbers = () => {
+    const numbers: (number | string)[] = [];
+
+    if (totalPages < 1) return [];
+    if (totalPages <= pagesToShow) {
+      for (let i = 1; i <= totalPages; i++) {
+        numbers.push(i);
+      }
+    } else if (currentPage <= 2) {
+      for (let i = 1; i <= 3; i++) {
+        numbers.push(i);
+      }
+      numbers.push('...');
+      numbers.push(totalPages - 2);
+      numbers.push(totalPages - 1);
+      numbers.push(totalPages);
+    } else if (currentPage >= totalPages - 1) {
+      numbers.push(1);
+      numbers.push(2);
+      numbers.push(3);
+      numbers.push('...');
+      for (let i = totalPages - 2; i <= totalPages; i++) {
+        numbers.push(i);
+      }
+    } else {
+      numbers.push(1);
+      numbers.push('...');
+      numbers.push(currentPage - 1);
+      numbers.push(currentPage);
+      numbers.push(currentPage + 1);
+      numbers.push('...');
+      numbers.push(totalPages);
+    }
+
+    return numbers;
+  };
+
+  useEffect(() => {
+    setPageNumbers(calculatePageNumbers());
+  }, [currentPage, totalBlogs]);
+
+  return (
+    <nav
+      aria-label="Blog pagination"
+      className="mt-8 flex items-center justify-center gap-2 p-4"
+    >
+      {/* Previous button */}
+      <Button
+        className={`${currentPage === 1 ? 'cursor-not-allowed opacity-50' : ''} size-[120px] rounded-l-md px-4 py-2`}
+        aria-label="Previous page"
+        bgClassName="bg-white"
+        textClassName="text-[#212525] font-inter text-[14px] font-normal"
+        text="Previous"
+        disabled={currentPage === 1}
+        onClick={() => paginate(currentPage - 1)}
+        icon={<IconArrowLeft className="inline-block size-4" />}
+        iconPosition={ButtonIconPosition.LEFT}
+      />
+      {/* Page numbers */}
+      <div className="flex w-[35vw] justify-center gap-3">
+        {pageNumbers.map((number, index) => (
+          <button
+            key={index}
+            className={`size-[40px] ${number === currentPage ? 'rounded border bg-[#6200EE] text-white' : 'text-[#6B6B6B]'}`}
+            aria-label={`${typeof number === 'number' ? `Go to page ${number}` : 'More pages'}`}
+            aria-current={number === currentPage ? 'page' : undefined}
+            onClick={() => typeof number === 'number' && paginate(number)}
+            disabled={number === '...'}
+          >
+            {number}
+          </button>
+        ))}
+      </div>
+      {/* Next button */}
+      <Button
+        className={`${currentPage === totalPages && 'cursor-not-allowed opacity-50'} h-[35px] w-[120px] rounded-l-md px-4 py-2`}
+        bgClassName="bg-white"
+        textClassName="text-[#212525] font-inter text-[14px] font-normal"
+        text="Next"
+        disabled={currentPage === totalPages}
+        onClick={() => paginate(currentPage + 1)}
+        icon={<IconArrowRight className="inline-block size-4" />}
+        iconPosition={ButtonIconPosition.RIGHT}
+      />
+    </nav>
+  );
+}
diff --git a/pages/blog/index.tsx b/pages/blog/index.tsx
index 37958cec4308..9b8d556436d0 100644
--- a/pages/blog/index.tsx
+++ b/pages/blog/index.tsx
@@ -1,9 +1,10 @@
 import { useRouter } from 'next/router';
-import React, { useContext, useEffect, useState } from 'react';
+import React, { useContext, useEffect, useMemo, useState } from 'react';
 
 import Empty from '@/components/illustrations/Empty';
 import GenericLayout from '@/components/layout/GenericLayout';
 import Loader from '@/components/Loader';
+import BlogPagination from '@/components/navigation/BlogPagination';
 import BlogPostItem from '@/components/navigation/BlogPostItem';
 import Filter from '@/components/navigation/Filter';
 import Heading from '@/components/typography/Heading';
@@ -32,106 +33,184 @@ export default function BlogIndexPage() {
 
           return i2Date.getTime() - i1Date.getTime();
         })
-      : []
+      : [],
   );
   const [isClient, setIsClient] = useState(false);
 
-  const onFilter = (data: IBlogPost[]) => setPosts(data);
+  const onFilter = (data: IBlogPost[]) => {
+    setPosts(data);
+  };
   const toFilter = [
     {
-      name: 'type'
+      name: 'type',
     },
     {
       name: 'authors',
-      unique: 'name'
+      unique: 'name',
     },
     {
-      name: 'tags'
-    }
+      name: 'tags',
+    },
   ];
   const clearFilters = () => {
-    router.push(`${router.pathname}`, undefined, {
-      shallow: true
-    });
+    const { page } = router.query;
+
+    router.push(
+      {
+        pathname: router.pathname,
+        query: { ...(page && { page }) },
+      },
+      undefined,
+      {
+        shallow: true,
+      },
+    );
   };
-  const showClearFilters = Object.keys(router.query).length > 0;
+  const showClearFilters = Object.keys(router.query).length > 1;
 
   const description = 'Find the latest and greatest stories from our community';
   const image = '/img/social/blog.webp';
+  const blogsPerPage = 9;
+
+  const currentPage = parseInt(router.query.page as string, 10) || 1;
+
+  const currentPosts = useMemo(() => {
+    const indexOfLastPost = currentPage * blogsPerPage;
+    const indexOfFirstPost = indexOfLastPost - blogsPerPage;
+
+    return posts.slice(indexOfFirstPost, indexOfLastPost);
+  }, [currentPage, posts]);
+
+  const paginate = (pageNumber: number) => {
+    const { query } = router;
+    const newQuery = {
+      ...query,
+      page: pageNumber,
+    };
+
+    router.push(
+      {
+        pathname: router.pathname,
+        query: newQuery,
+      },
+      undefined,
+      {
+        shallow: true,
+      },
+    );
+  };
+
+  useEffect(() => {
+    if (router.isReady && !router.query.page) {
+      router.replace(
+        { pathname: router.pathname, query: { page: '1' } },
+        undefined,
+        { shallow: true },
+      );
+    }
+  }, [router.isReady]);
 
   useEffect(() => {
-    setIsClient(true);
-  }, []);
+    if (router.isReady) {
+      setIsClient(true);
+    }
+  }, [router.isReady]);
 
   return (
-    <GenericLayout title='Blog' description={description} image={image} wide>
-      <div className='relative px-4 pb-20 pt-8 sm:px-6 lg:px-8 lg:pb-28 lg:pt-12' id='main-content'>
-        <div className='absolute inset-0'>
-          <div className='h-1/3 bg-white sm:h-2/3'></div>
+    <GenericLayout title="Blog" description={description} image={image} wide>
+      <div
+        className="relative px-4 pb-20 pt-8 sm:px-6 lg:px-8 lg:pb-28 lg:pt-12"
+        id="main-content"
+      >
+        <div className="absolute inset-0">
+          <div className="h-1/3 bg-white sm:h-2/3"></div>
         </div>
-        <div className='relative mx-auto max-w-7xl'>
-          <div className='text-center'>
+        <div className="relative mx-auto max-w-7xl">
+          <div className="text-center">
             <Heading level={HeadingLevel.h1} typeStyle={HeadingTypeStyle.lg}>
               Welcome to our blog!
             </Heading>
-            <Paragraph className='mx-auto mt-3 max-w-2xl sm:mt-4'>
+            <Paragraph className="mx-auto mt-3 max-w-2xl sm:mt-4">
               Find the latest and greatest stories from our community
             </Paragraph>
-            <Paragraph typeStyle={ParagraphTypeStyle.md} className='mx-auto mt-4 max-w-2xl'>
+            <Paragraph
+              typeStyle={ParagraphTypeStyle.md}
+              className="mx-auto mt-4 max-w-2xl"
+            >
               Want to publish a blog post? We love community stories.{' '}
-              <TextLink href='https://github.com/asyncapi/website/issues/new?template=blog.md' target='_blank'>
+              <TextLink
+                href="https://github.com/asyncapi/website/issues/new?template=blog.md"
+                target="_blank"
+              >
                 Submit yours!
               </TextLink>
             </Paragraph>
-            <Paragraph typeStyle={ParagraphTypeStyle.md} className='mx-auto mt-1 max-w-2xl'>
+            <Paragraph
+              typeStyle={ParagraphTypeStyle.md}
+              className="mx-auto mt-1 max-w-2xl"
+            >
               We have an
               <img
-                className='ml-1 text-primary-500 hover:text-primary-300'
+                className="ml-1 text-primary-500 hover:text-primary-300"
                 style={{ display: 'inline' }}
-                src='/img/logos/rss.svg'
-                alt='RSS feed'
-                height='18px'
-                width='18px'
+                src="/img/logos/rss.svg"
+                alt="RSS feed"
+                height="18px"
+                width="18px"
               />
-              <TextLink href='/rss.xml'> RSS Feed</TextLink>, too!
+              <TextLink href="/rss.xml"> RSS Feed</TextLink>, too!
             </Paragraph>
           </div>
-          <div className='mx:64 mt-12 md:flex md:justify-center lg:justify-start'>
+          <div className="mx:64 mt-12 md:flex md:justify-center lg:justify-start">
             <Filter
               data={navItems || []}
               onFilter={onFilter}
-              className='md: mx-px mt-1 w-full md:mt-0 md:w-1/5 md:text-sm'
+              className="md: mx-px mt-1 w-full md:mt-0 md:w-1/5 md:text-sm"
               checks={toFilter}
             />
             {showClearFilters && (
               <button
-                type='button'
-                className='bg-none text-md mt-1 rounded-md border border-gray-200 px-4 py-2 font-semibold tracking-heading text-gray-800 shadow-none transition-all duration-500 ease-in-out hover:text-gray-700 md:mt-0 md:py-0'
+                type="button"
+                className="bg-none text-md mt-1 rounded-md border border-gray-200 px-4 py-2 font-semibold tracking-heading text-gray-800 shadow-none transition-all duration-500 ease-in-out hover:text-gray-700 md:mt-0 md:py-0"
                 onClick={clearFilters}
               >
-                <span className='inline-block'>Clear filters</span>
+                <span className="inline-block">Clear filters</span>
               </button>
             )}
           </div>
           <div>
-            {Object.keys(posts).length === 0 && (
-              <div className='mt-16 flex flex-col items-center justify-center'>
+            {(Object.keys(posts).length === 0 ||
+              Object.keys(currentPosts).length === 0) && (
+              <div className="mt-16 flex flex-col items-center justify-center">
                 <Empty />
-                <p className='mx-auto mt-3 max-w-2xl text-xl leading-7 text-gray-500'>No post matches your filter</p>
+                <p className="mx-auto mt-3 max-w-2xl text-xl leading-7 text-gray-500">
+                  No post matches your filter
+                </p>
               </div>
             )}
             {Object.keys(posts).length > 0 && isClient && (
-              <ul className='mx-auto mt-12 grid max-w-lg gap-5 lg:max-w-none lg:grid-cols-3'>
-                {posts.map((post, index) => (
+              <ul className="mx-auto mt-12 grid max-w-lg gap-5 lg:max-w-none lg:grid-cols-3">
+                {currentPosts.map((post, index) => (
                   <BlogPostItem key={index} post={post} />
                 ))}
               </ul>
             )}
             {Object.keys(posts).length > 0 && !isClient && (
-              <div className='h-screen w-full'>
-                <Loader loaderText='Loading Blogs' className='mx-auto my-60' pulsating />
+              <div className="h-screen w-full">
+                <Loader
+                  loaderText="Loading Blogs"
+                  className="mx-auto my-60"
+                  pulsating
+                />
               </div>
             )}
+            {/* Pagination component */}
+            <BlogPagination
+              blogsPerPage={blogsPerPage}
+              totalBlogs={posts.length}
+              paginate={paginate}
+              currentPage={currentPage}
+            />
           </div>
         </div>
       </div>