","language":"html"},{"_key":"3298c9f63dba","_type":"block","children":[{"_key":"9c3c091c8a14","_type":"span","marks":[],"text":"Within the same index.js file, we can create div tags with ids to specify where each app will be mounted."}],"markDefs":[],"style":"normal"},{"_key":"fb0fcb4f1049","_type":"code","code":"// Code snippet 3 – index.ejs\n\n
\n \n \n
\n","language":"html"},{"_key":"fd0e3a9c483a","_type":"block","children":[{"_key":"b83d9c165c63","_type":"span","marks":[],"text":"The sidebar application will be loaded in the div with id = \"sidebar-container\" The employee, project and techdesk application will be loaded, one at a time, within the div with id = \"app-container\""}],"markDefs":[],"style":"normal"},{"_key":"391d6d4f4340","_type":"block","children":[{"_key":"dec998b11eda","_type":"span","marks":[],"text":"2.2 Applications"}],"markDefs":[],"style":"h2"},{"_key":"4ba13fe42251","_type":"block","children":[{"_key":"248d1e608da0","_type":"span","marks":["strong"],"text":"2.2.1"},{"_key":"d5c34a2672c0","_type":"span","marks":[],"text":" We need to create an application folder for each of the applications. We can then run create-single-spa within each folder. This time we will choose the option \"single-spa application/parcel\" In framework, we will choose the framework that will be used to build the application. This creates a project with 3 files in src folder. Within the hr-sidebar folder it will create"}],"markDefs":[],"style":"normal"},{"_key":"ecb7d14a77e6","_type":"block","children":[{"_key":"1dee1bb90cbd","_type":"span","marks":[],"text":"hr-sidebar.js"}],"level":1,"listItem":"bullet","markDefs":[],"style":"normal"},{"_key":"a9168633324f","_type":"block","children":[{"_key":"3eb0bcc3400c","_type":"span","marks":[],"text":"root.component.js"}],"level":1,"listItem":"bullet","markDefs":[],"style":"normal"},{"_key":"0c3db7bfbb05","_type":"block","children":[{"_key":"dc54c24540ea","_type":"span","marks":[],"text":"root.component.test.js"}],"level":1,"listItem":"bullet","markDefs":[],"style":"normal"},{"_key":"61d8ec95ae51","_type":"block","children":[{"_key":"e191a2390ab0","_type":"span","marks":["strong"],"text":"2.2.2"},{"_key":"21585c09b977","_type":"span","marks":[],"text":" In the hr-sidebar.js file we need to wrap React, ReactDOM and the root component with single-spa-react (for react application). Similarly, if it is an angular application, it should be wrapped in single-spa-angular and so on. Also, we must export three lifecycle functions, bootstrap, mount and unmount. "},{"_key":"54686c99c8ef","_type":"span","marks":["strong"],"text":"Bootstrap"},{"_key":"f8ad57047d87","_type":"span","marks":[],"text":" will be called only once when the child application is initialized, "},{"_key":"9b5bb1903389","_type":"span","marks":["strong"],"text":"mount"},{"_key":"c51e335cbd21","_type":"span","marks":[],"text":" will be triggered every time the application is loaded. "},{"_key":"a3cf4af3e049","_type":"span","marks":["strong"],"text":"Unmount"},{"_key":"c989796460a5","_type":"span","marks":[],"text":" is called each time application is unloaded. "},{"_key":"78f771c72242","_type":"span","marks":["strong"],"text":"domElementGetter"},{"_key":"5c4fb19e8d49","_type":"span","marks":[],"text":" function is optional and can be used to specify the dom element where the application will be mounted."}],"markDefs":[],"style":"normal"},{"_key":"f55e1b48a296","_type":"code","code":"// Code snippet 4 - hr-sidebar.js\nimport React from \"react\";\nimport ReactDOM from \"react-dom\";\nimport singleSpaReact from \"single-spa-react\";\nimport Root from \"./root.component\";\nconst lifecycles = singleSpaReact({\n React,\n ReactDOM,\n rootComponent: Root,\n domElementGetter\n});\nexport const { bootstrap, mount, unmount } = lifecycles;\nfunction domElementGetter() {\n return document.getElementById(\"sidebar-container\")\n}","language":"javascript"},{"_key":"638f15162548","_type":"block","children":[{"_key":"e55a0a87d34b","_type":"span","marks":["strong"],"text":"2.2.3"},{"_key":"a0fc4582732d","_type":"span","marks":[],"text":" The root.component.js will have the application content. Here, we can return the App component which has the entire application."}],"markDefs":[],"style":"normal"},{"_key":"e47264c5bd52","_type":"code","code":"// Code snippet 5 – root.component.js\nimport App from './App'\nexport default function Root(props) {\n return ; \n}","language":"javascript"},{"_key":"27b159f0f432","_type":"block","children":[{"_key":"fdb8ba925200","_type":"span","marks":[],"text":"The package.json has scripts for running the application in stand-alone mode or as a micro frontend application."}],"markDefs":[],"style":"normal"},{"_key":"d239b8fc2361","_type":"code","code":"// Code snippet 6 – package.json\n \"name\": \"@example/hr-sidebar\",\n \"scripts\": {\n \"start\": \"webpack serve\",\n \"start:standalone\": \"webpack serve --env standalone\"\n …","language":"json"},{"_key":"064d3ee8c387","_type":"block","children":[{"_key":"a314fede6320","_type":"span","marks":[],"text":"Once all the applications are setup, we can run the root config application. The other applications will be loaded and depending on the application URL, they will be mounted or unmounted."}],"markDefs":[],"style":"normal"},{"_key":"a4034822d74e","_type":"block","children":[{"_key":"31e8fec494e2","_type":"span","marks":[],"text":"Since the hr-sidebar application is active whenever the \"/\" route is active, it will always be mounted and displayed in element with id = \"sidebar-container\""}],"markDefs":[],"style":"normal"},{"_key":"7b538569cc5c","_type":"block","children":[{"_key":"8d0899d3f08d","_type":"span","marks":[],"text":"Whenever the employee icon is chosen, application route will be /employee. The hr-employee application will be mounted and displayed in the element with id = \"app-container.\""}],"markDefs":[],"style":"normal"},{"_key":"d5e583b7a521","_type":"block","children":[{"_key":"fc5a00fafc8e","_type":"span","marks":[],"text":"Similarly, when project and techdesk icons are chosen, hr-project and hr-techdesk applications are mounted respectively. They will also be displayed in element with id = \"app-container.\""}],"markDefs":[],"style":"normal"},{"_key":"7ba2145e7fbf","_type":"block","children":[{"_key":"a386b89ac9c1","_type":"span","marks":[],"text":"3. Qiankun"}],"markDefs":[],"style":"h2"},{"_key":"0b99e2f032f6","_type":"block","children":[{"_key":"ba5487ce9be0","_type":"span","marks":[],"text":"Qiankun is based on single-spa and aims to make the implementation easier."}],"markDefs":[],"style":"normal"},{"_key":"bd1f06501726","_type":"block","children":[{"_key":"a0ea587e7655","_type":"span","marks":[],"text":"Qiankun apps consist of a main application and multiple sub applications."}],"markDefs":[],"style":"normal"},{"_key":"466eee1a466a","_type":"block","children":[{"_key":"6f7ff02828eb","_type":"span","marks":[],"text":"The sub applications are mounted and unmounted based on routes of the main application."}],"markDefs":[],"style":"normal"},{"_key":"c1213c56b084","_type":"block","children":[{"_key":"33c2ac7abb7b","_type":"span","marks":[],"text":"The main application must install qiankun dependency and register the sub applications."}],"markDefs":[],"style":"normal"},{"_key":"e1f53106855a","_type":"block","children":[{"_key":"b9b1d18d7cfb","_type":"span","marks":[],"text":"Each sub application needs to export bootstrap, mount, and unmount, three lifecycle hooks, in its own entry javascript file. They also need to add some configuration to the application bundler. This is done so that main application can correctly identify information exposed by sub application."}],"markDefs":[],"style":"normal"},{"_key":"3312c71a512d","_type":"block","children":[{"_key":"aeb17641f191","_type":"span","marks":[],"text":"3.1 Main application"}],"markDefs":[],"style":"h2"},{"_key":"3beec2c1c373","_type":"block","children":[{"_key":"db8c9c5e7677","_type":"span","marks":["strong"],"text":"3.1.1"},{"_key":"d81558d34832","_type":"span","marks":[],"text":" After installing the qiankun dependency, at the entry point of the main application, we should register the sub applications."}],"markDefs":[],"style":"normal"},{"_key":"a623af41d454","_type":"code","code":"// Code snippet 7 – index.js\nimport React from 'react';\nimport ReactDOM from 'react-dom';\nimport { registerMicroApps, start, setDefaultMountApp } from \"qiankun\"; \nimport subApps from './sub-apps';\n\nconst root = ReactDOM.createRoot(document.getElementById('root'));\nroot.render();\nregisterMicroApps(subApps);\nsetDefaultMountApp(\"/employee\");\nstart();","language":"javascript"},{"_key":"4fe34ad4c0d7","_type":"block","children":[{"_key":"7eef3edcb9a7","_type":"span","marks":[],"text":"Setting of the default app to be mounted is optional."}],"markDefs":[],"style":"normal"},{"_key":"812963524b1e","_type":"block","children":[{"_key":"209b600ea539","_type":"span","marks":["strong"],"text":"3.1.2"},{"_key":"42fa6f3cd3fa","_type":"span","marks":[],"text":" The sub applications are defined as"}],"markDefs":[],"style":"normal"},{"_key":"6bd8c3070cfb","_type":"code","code":"// Code snippet 8 – subApps.js\nconst subApps = [\n {\n name: 'employee', // app name registered\n entry: //dev-employee/hr.com,\n container: '#subapp-container',\n activeRule: '/employee'\n },\n{\n name: 'project', // app name registered\n entry: //dev-project/hr.com,\n container: '#subapp-container',\n activeRule: '/project'\n },\n {\n name: 'techdesk', // app name registered\n entry: //dev-techdesk/hr.com,\n container: '#subapp-container',\n activeRule: '/techdesk'\n },\n];\nexport default subApps;","language":"javascript"},{"_key":"dc64fd6ea735","_type":"block","children":[{"_key":"e68a03797a86","_type":"span","marks":[],"text":"The microfrontends core team recommends that when we should only work with one micro frontend application in local at a time, rest should be already deployed. The Employee, Project and Techdesk application are already deployed in dev."}],"markDefs":[],"style":"normal"},{"_key":"13f002d0a412","_type":"block","children":[{"_key":"3d3714fdad96","_type":"span","marks":["strong"],"text":"3.1.3"},{"_key":"ce5c8cafc4ee","_type":"span","marks":[],"text":" However, if we want to test the application before deploying, we can register the applications as below"}],"markDefs":[],"style":"normal"},{"_key":"4a140cee67db","_type":"code","code":"// Code snippet 9 - subApps.js\nconst subApps = [\n {\n name: 'employee', // app name registered\n entry: //localhost:7001,\n container: '#subapp-container',\n activeRule: '/employee'\n },\n{\n name: 'project', // app name registered\n entry: //localhost:7002,\n container: '#subapp-container',\n activeRule: '/project'\n },\n {\n name: 'techdesk', // app name registered\n entry: //localhost:7003,\n container: '#subapp-container',\n activeRule: '/techdesk'\n },\n];\nexport default subApps;","language":"javascript"},{"_key":"b2bfe1336cf5","_type":"block","children":[{"_key":"54ff917da7ec","_type":"span","marks":[],"text":"From the main application whenever we go to the route /employee, employee application will be displayed in the element with id \"subapp-container\", when we go to route and so on."}],"markDefs":[],"style":"normal"},{"_key":"48c3838aa983","_type":"block","children":[{"_key":"8c5b4a1c4946","_type":"span","marks":[],"text":"The html element with id = \"subapp-container\" is the area surrounded by blue border."}],"markDefs":[],"style":"normal"},{"_key":"a63fa15d53db","_type":"block","children":[{"_key":"53a6a59cf140","_type":"span","marks":[],"text":"All sub applications whose activeRule matches the URL being called will be loaded there."}],"markDefs":[],"style":"normal"},{"_key":"a7fcc0aa64fb","_type":"block","children":[{"_key":"229dd0ea573b","_type":"span","marks":[],"text":"Note: The header and sidebar are part of the main application here."}],"markDefs":[],"style":"normal"},{"_key":"a07ffa4d165c","_type":"block","children":[{"_key":"82a27d11eb39","_type":"span","marks":["strong"],"text":"3.2"},{"_key":"9c2134352065","_type":"span","marks":[],"text":" Sub Applications"}],"markDefs":[],"style":"normal"},{"_key":"f24309b8d8d9","_type":"block","children":[{"_key":"ae25502e22ed","_type":"span","marks":[],"text":"Note: We are considering only sub applications built with webpack (Vue, React, Angular)"}],"markDefs":[],"style":"normal"},{"_key":"414fdd261ad4","_type":"block","children":[{"_key":"8676e71fa63c","_type":"span","marks":[],"text":"For all applications with webpack, publicPath specifies the base path for assets within the application."}],"markDefs":[],"style":"normal"},{"_key":"f5bfb13d3c7c","_type":"block","children":[{"_key":"f212e5ece413","_type":"span","marks":[],"text":"To make an application behave as a qiankun sub application, we need to modify the publicPath at runtime, such that it is the one provided by qiankun (i.e. the path of the main application)."}],"markDefs":[],"style":"normal"},{"_key":"77a22fc10e73","_type":"block","children":[{"_key":"07f57a8b034a","_type":"span","marks":["strong"],"text":"3.2.1"},{"_key":"18bba37aa269","_type":"span","marks":[],"text":" We can create file public-path.js within src folder."}],"markDefs":[],"style":"normal"},{"_key":"7164a4e428b5","_type":"code","code":"// Code snippet 10 – public-path.js\nif (window.__POWERED_BY_QIANKUN__) {\n __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;\n}","language":"javascript"},{"_key":"16fc6fbe3682","_type":"block","children":[{"_key":"b22609b23793","_type":"span","marks":["strong"],"text":"3.2.2"},{"_key":"07cdc85f4d7e","_type":"span","marks":[],"text":" Next, we need to import the public-path.js file right at the top of the entry file index.js. We also modify the ReactDOM. render and export the bootstrap, mount, and unmount functions."}],"markDefs":[],"style":"normal"},{"_key":"65898f7007fd","_type":"code","code":"// Code snippet 11 \nimport './public-path';\nimport React from 'react';\nimport ReactDOM from 'react-dom';\nimport App from './App';\n\nif (!window.__POWERED_BY_QIANKUN__) {\n ReactDOM.render( \n \n document.getElementById('root')\n );\n}\nexport async function bootstrap() {\n console.log('employee management bootstrapped');\n}\nexport async function mount(props) {\n const { container } = props;\n ReactDOM.render(\n ,\n container ? container.querySelector('#root') : document.querySelector('#root')\n );\n}\nexport async function unmount(props) {\n const { container } = props;\n ReactDOM.unmountComponentAtNode(\n container ? container.querySelector('#root') : document.querySelector('#root')\n );\n}","language":"javascript"},{"_key":"e72fa28bb5c7","_type":"block","children":[{"_key":"9165303ed1be","_type":"span","marks":["strong"],"text":"3.2.3"},{"_key":"6001d053bd43","_type":"span","marks":[],"text":" Finally, we can modify the webpack configuration using @rescripts/cli or react-app-wired plugin."}],"markDefs":[],"style":"normal"},{"_key":"f6ab58d05dc4","_type":"block","children":[{"_key":"476daf4a5de2","_type":"span","marks":[],"text":"Using react-app-wired plugin, the config modifications can be specified in config-overrides file in root directory."}],"markDefs":[],"style":"normal"},{"_key":"159e2304caef","_type":"block","children":[{"_key":"c3285ea581d8","_type":"span","marks":[],"text":"All npm scripts in package.json can be modified to use react-app-rewired command instead of react-scripts."}],"markDefs":[],"style":"normal"},{"_key":"51e9ef5520b8","_type":"code","code":"// Code snippet 12 – config-overrides.js file\nconst { name } = require('./package.json');\nmodule.exports = {\n webpack: (config) => {\n config.output.library = `${name}-[name]`;\n config.output.libraryTarget = 'umd';\n config.output.chunkLoadingGlobal = `webpackJsonp_${name}`;\n config.output.globalObject = 'window';\n return config;\n },\n devServer: (configFunction) => {\n return function (proxy, allowedHost) {\n const config = configFunction(proxy, allowedHost);\n config.open = false;\n config.hot = false;\n config.headers = {\n 'Access-Control-Allow-Origin': '*'\n };\n return config;\n };\n }\n};","language":"javascript"},{"_key":"74547b42da6d","_type":"code","code":"// Code snippet 13 – package.json\n \"scripts\": {\n \"start\": \"react-app-rewired start\",\n \"build\": \"react-app-rewired build\",\n \"test\": \"react-app-rewired test\",\n \"eject\": \"react-scripts eject\"\n },","language":"json"},{"_key":"6c07463274a9","_type":"block","children":[{"_key":"f6ff71f4d180","_type":"span","marks":[],"text":"Once the above setup is done, we can run the main application. Whenever the employee icon is chosen, it will go to the /employee route, and Employee Management application will run and be displayed in the element with id = \"subapp-container.\""}],"markDefs":[],"style":"normal"},{"_key":"76d8c51dafd1","_type":"block","children":[{"_key":"eba6a354d1c7","_type":"span","marks":[],"text":"Similarly, when project and techdesk icons are chosen it will run Project Management and Techdesk applications respectively."}],"markDefs":[],"style":"normal"},{"_key":"fa06ad00ed55","_type":"block","children":[{"_key":"0d5c00355bd9","_type":"span","marks":[],"text":"Conclusion"}],"markDefs":[],"style":"h2"},{"_key":"402c95b484c8","_type":"block","children":[{"_key":"be097f8765cd","_type":"span","marks":[],"text":"The Micro frontend architecture can benefit teams greatly if they are working on large complex applications. However, careful planning is required to leverage its advantages. All microfrontends within an application should have consistent look and feel. If micro frontends need to communicate with each other, they can use custom props while registering the application. Teams developing different micro frontends need to regularly communicate with each other to prevent component or logic duplication."}],"markDefs":[],"style":"normal"},{"_key":"0b31b8d40148","_type":"block","children":[{"_key":"3bb839dd3c4c","_type":"span","marks":[],"text":"Once the above points are taken care of, Micro frontends are a great way to increase efficiency and the turnaround time for adding new features."}],"markDefs":[],"style":"normal"},{"_key":"fad6f5b90e03","_type":"block","children":[{"_key":"0057a264e83d","_type":"span","marks":[],"text":"References"}],"markDefs":[],"style":"h2"},{"_key":"fae58807ac27","_type":"block","children":[{"_key":"e4926f0764d7","_type":"span","marks":[],"text":"https://single-spa.js.org/docs/getting-started-overview https://qiankun.umijs.org/guide/getting-started https://qiankun.umijs.org/guide/tutorial "}],"markDefs":[],"style":"normal"}],"category":"Engineering","excerpt":"The Micro frontend architecture allows us to divide a web application into individual applications working loosely together. Each application, also known as a micro frontend, is an independent smaller module of the web application that can be build and run independently. These can be developed using different frameworks, allowing companies to leverage the expertise of team members specializing in different technologies.","featuredImage":{"alt":"Micro Frontend using Single SPA and Qiankun","asset":{"_id":"image-0b85f3ab3ae940367b08ec342639d4792afec8a5-1417x942-png","url":"https://cdn.sanity.io/images/ygstncxq/production/0b85f3ab3ae940367b08ec342639d4792afec8a5-1417x942.png"}},"publishedAt":"2024-04-09T00:00:00.000Z","seo":{"_type":"seo","metaDescription":"The Micro frontend architecture allows us to divide a web application into individual applications working loosely together. Each application, also known as a m","metaTitle":"Micro Frontend using Single SPA and Qiankun"},"slug":{"_type":"slug","current":"micro-frontend-single-spa-qiankun"},"subjects":["Micro Frontend","SPA","Qiankun","Web app","Web development"],"title":"Micro Frontend using Single SPA and Qiankun"}],["*[_type == \"blogPost\"] | order(publishedAt desc) {\n _id, title, slug, publishedAt, category, excerpt,\n featuredImage { asset->{_id, url}, alt },\n author->{ name, photo { asset->{_id, url} } }\n}::",[{"_id":"blogPost-encouraging-open-dialogue-with-hr","author":{"name":"Sachin Biju","photo":null},"category":"Engineering","excerpt":"HR departments are evolving beyond rule enforcement to become trusted partners in employee well-being. This article explores how organizations can move past open-door policies to build genuine psychological safety, enabling employees to speak freely with HR through trust, transparency, and consistent action.","featuredImage":{"alt":"From Policies to Trust: Encouraging Open Dialogue with HR","asset":{"_id":"image-cf34b8d50a0a406ec3d0e7c085c2331775708788-2125x1413-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/cf34b8d50a0a406ec3d0e7c085c2331775708788-2125x1413.jpg"}},"publishedAt":"2025-12-02T00:00:00.000Z","slug":{"_type":"slug","current":"encouraging-open-dialogue-with-hr"},"title":"From Policies to Trust: Encouraging Open Dialogue with HR"},{"_id":"blogPost-designing-a-blazing-fast-warm-data-ingestion-pipeline","author":{"name":"Aditya Arora","photo":null},"category":"Engineering","excerpt":"Building streaming data architectures that transform JSON payloads into relational tables can quickly become complex. This article explores how to design an elegant warm data ingestion pipeline using SingleStore's native Kafka support and Azure Event Hubs to achieve millisecond-latency data processing without the overhead of traditional ETL stacks.","featuredImage":{"alt":"High-Performance Warm Data Ingestion with SingleStore & Event Hubs","asset":{"_id":"image-6b83089758493bf0f9232a1371a15546dff02222-2125x1413-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/6b83089758493bf0f9232a1371a15546dff02222-2125x1413.jpg"}},"publishedAt":"2025-11-20T00:00:00.000Z","slug":{"_type":"slug","current":"designing-a-blazing-fast-warm-data-ingestion-pipeline"},"title":"High-Performance Warm Data Ingestion with SingleStore & Event Hubs"},{"_id":"blogPost-the-human-alogorithm","author":{"name":"Anisha Mariam Thomas","photo":{"asset":{"_id":"image-d31ce30d8b4d5b0808d049b98f3698eec465425f-450x450-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/d31ce30d8b4d5b0808d049b98f3698eec465425f-450x450.jpg"}}},"category":"Engineering","excerpt":"Discover why genuine human connection remains the ultimate competitive advantage in HR. Learn which aspects of employee engagement, mental health, and workplace culture AI cannot replicate—and how to preserve the humane touch while embracing automation.","featuredImage":{"alt":"The Human Algorithm: Why the Humane Touch in HR Still Outperforms AI","asset":{"_id":"image-60f404116c3b478bbe39b8d9ad60f09821ca0407-2125x1413-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/60f404116c3b478bbe39b8d9ad60f09821ca0407-2125x1413.jpg"}},"publishedAt":"2025-11-10T00:00:00.000Z","slug":{"_type":"slug","current":"the-human-alogorithm"},"title":"The Human Algorithm: Why the Humane Touch in HR Still Outperforms AI"},{"_id":"blogPost-strapi-migration-v3-v4","author":{"name":"Ashish Sharma","photo":null},"category":"Engineering","excerpt":"Complete guide to migrating Strapi CMS from v3 to v4. Learn how to handle schema changes, foreign key constraints, and data relationships with practical solutions and production-ready scripts.","featuredImage":{"alt":"Mastering Strapi Data Migrations: A Real-World Journey from v3 to v4","asset":{"_id":"image-8503c1ab2bd83a77ec0878c52c44141dec53cfc0-680x452-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/8503c1ab2bd83a77ec0878c52c44141dec53cfc0-680x452.jpg"}},"publishedAt":"2025-10-15T00:00:00.000Z","slug":{"_type":"slug","current":"strapi-migration-v3-v4"},"title":"Mastering Strapi Data Migrations: A Real-World Journey from v3 to v4"},{"_id":"blogPost-cost-effective-athena-partition-management","author":{"name":"Azhar MA","photo":null},"category":"Engineering","excerpt":"Discover how to automatically manage Athena partitions for real-time data pipelines without breaking the bank. Learn a cost-effective approach that provides immediate data availability while scaling better than traditional AWS Glue Crawlers—achieving 99%+ cost savings for large datasets.","featuredImage":{"alt":"Cost-Effective Athena Partition Management: Beyond Glue Crawlers","asset":{"_id":"image-1d8b7432b0d49fcfb1bbe6081a5ba80b837dcbec-1360x904-png","url":"https://cdn.sanity.io/images/ygstncxq/production/1d8b7432b0d49fcfb1bbe6081a5ba80b837dcbec-1360x904.png"}},"publishedAt":"2025-10-03T00:00:00.000Z","slug":{"_type":"slug","current":"cost-effective-athena-partition-management"},"title":"Cost-Effective Athena Partition Management: Beyond Glue Crawlers"},{"_id":"blogPost-archiving-service-logs-from-opensearch-to-s3","author":{"name":"Ashish Sharma","photo":null},"category":"Engineering","excerpt":"A complete end-to-end guide for isolating Kubernetes service logs, routing them through OpenSearch for real-time querying, and archiving them to Amazon S3. Learn how to optimize your search cluster performance while maintaining compliance-ready log archives.","featuredImage":{"alt":"Archiving Service Logs from OpenSearch to S3: A Comprehensive Guide","asset":{"_id":"image-70e67bc892fb25029f7970029764cffdd8766f6b-2125x1412-png","url":"https://cdn.sanity.io/images/ygstncxq/production/70e67bc892fb25029f7970029764cffdd8766f6b-2125x1412.png"}},"publishedAt":"2025-09-23T00:00:00.000Z","slug":{"_type":"slug","current":"archiving-service-logs-from-opensearch-to-s3"},"title":"Archiving Service Logs from OpenSearch to S3: A Comprehensive Guide"},{"_id":"blogPost-breaking-the-thread-barrier","author":{"name":"Azhar MA","photo":null},"category":"Engineering","excerpt":"A deep dive into Java performance optimization using AsyncContext for API scaling. Learn how we scaled from struggling at 1000 req/sec to comfortably handling 1500+ req/sec with 75% fewer threads through thread pool optimization, all without changing a single line of client code.","featuredImage":{"alt":"From Bottleneck to 1000+ RPS: Zero-Downtime API Scaling","asset":{"_id":"image-a0f195613a2c5e4592489224a932225370aff27f-2833x1883-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/a0f195613a2c5e4592489224a932225370aff27f-2833x1883.jpg"}},"publishedAt":"2025-08-27T00:00:00.000Z","slug":{"_type":"slug","current":"breaking-the-thread-barrier"},"title":"From Bottleneck to 1000+ RPS: Zero-Downtime API Scaling"},{"_id":"blogPost-fuzz-testing-breaking-things-to-build-them","author":{"name":"AryaKrishna AB","photo":null},"category":"Engineering","excerpt":"Complete guide to fuzz testing and fuzzing techniques for software security. Learn what is fuzz testing, how to do fuzz testing, fuzzing tools, and build your own fuzzer. Discover fuzz test strategies, fuzzing cyber security practices, and fuzzing attack prevention methods to enhance software reliability and security.","featuredImage":{"alt":"Fuzz Testing: Breaking Things to Build Them Better","asset":{"_id":"image-5dc5c964c9556d42e2312f961a0612df81ce8190-2833x1883-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/5dc5c964c9556d42e2312f961a0612df81ce8190-2833x1883.jpg"}},"publishedAt":"2025-08-22T00:00:00.000Z","slug":{"_type":"slug","current":"fuzz-testing-breaking-things-to-build-them"},"title":"Fuzz Testing: Breaking Things to Build Them Better"},{"_id":"blogPost-building-a-serverless-video-format-converter-with-aws-lambda","author":{"name":"Azhar MA","photo":null},"category":"Engineering","excerpt":"In the world of video streaming and content delivery, video codec compatibility remains a significant challenge. While H.265 (HEVC) offers superior compression efficiency, H.264 (AVC) still dominates in terms of device compatibility and browser support. This blog post details the journey of building a serverless video format converter using AWS Lambda that automatically processes uploaded videos, detects H.265 encoded content, and converts it to the more widely compatible H.264 format.","featuredImage":{"alt":"Building a Serverless Video Format Converter with AWS Lambda","asset":{"_id":"image-4f00d474d9eccbe37f646006cb7d8e825f21d073-2833x1883-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/4f00d474d9eccbe37f646006cb7d8e825f21d073-2833x1883.jpg"}},"publishedAt":"2025-08-10T00:00:00.000Z","slug":{"_type":"slug","current":"building-a-serverless-video-format-converter-with-aws-lambda"},"title":"Building a Serverless Video Format Converter with AWS Lambda"},{"_id":"blogPost-unleashing-advanced-analytics-with-tabpy","author":{"name":"Ausaf Razvi","photo":null},"category":"Engineering","excerpt":"Tableau's visualization capabilities are powerful, but what happens when you need advanced statistical modeling or custom algorithms? TabPy (Tableau Python Server) bridges this gap by allowing seamless integration of Python scripts directly into Tableau workflows, unlocking the full potential of Python's data science ecosystem.","featuredImage":{"alt":"Bridging Tableau and Python: Unleashing Advanced Analytics with TabPy","asset":{"_id":"image-ce0d658bb279564a62bee17634d3f20589b3ef87-2833x1883-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/ce0d658bb279564a62bee17634d3f20589b3ef87-2833x1883.jpg"}},"publishedAt":"2025-07-28T00:00:00.000Z","slug":{"_type":"slug","current":"unleashing-advanced-analytics-with-tabpy"},"title":"Bridging Tableau and Python: Unleashing Advanced Analytics with TabPy"},{"_id":"blogPost-vite_memory_leaks","author":{"name":"Nismal M","photo":null},"category":"Engineering","excerpt":"Vite's lightning-fast performance can degrade in large applications due to memory leaks. This comprehensive guide explores the root causes, diagnostic techniques, and proven solutions for maintaining optimal Vite performance in enterprise-scale codebases.","featuredImage":{"alt":"Debugging and Fixing Vite Memory Leaks in Large-Scale Applications","asset":{"_id":"image-a445ddcb89e1564147deb19dc249f21decf2e629-2833x1883-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/a445ddcb89e1564147deb19dc249f21decf2e629-2833x1883.jpg"}},"publishedAt":"2025-07-18T00:00:00.000Z","slug":{"_type":"slug","current":"vite_memory_leaks"},"title":"Debugging and Fixing Vite Memory Leaks in Large-Scale Applications"},{"_id":"blogPost-optimizing-web-performance-part-2","author":{"name":"Faiz Ahmed Khan","photo":null},"category":"Engineering","excerpt":"Beyond network optimization lies the real performance battleground. Explore advanced techniques for rendering pattern optimization, build-time optimizations, and React-specific strategies that transform sluggish applications into lightning-fast user experiences.","featuredImage":{"alt":"Optimizing Web Performance: Faster User Experiences – Part 2","asset":{"_id":"image-eefd3e711c2ec010d9186ed11a298ad14aaf2c59-2833x1883-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/eefd3e711c2ec010d9186ed11a298ad14aaf2c59-2833x1883.jpg"}},"publishedAt":"2025-07-10T00:00:00.000Z","slug":{"_type":"slug","current":"optimizing-web-performance-part-2"},"title":"Optimizing Web Performance: Faster User Experiences – Part 2"},{"_id":"blogPost-a-deep-dive-into-nvidia-newton","author":{"name":"Ausaf Razvi","photo":null},"category":"Engineering","excerpt":"In March 2025, NVIDIA unveiled Newton, a powerful, open-source physics engine that could redefine how we simulate and train robotic systems. Co-developed with Google DeepMind and Disney Research, Newton merges advanced physical modeling with the raw power of GPU acceleration—opening new frontiers in robotics, machine learning, and immersive AI interaction.","featuredImage":{"alt":"With Great Physics Comes Great Responsibility: A Deep Dive into NVIDIA Newton","asset":{"_id":"image-b02ba65577a71425832cc4b8a5452b301e2f17fb-3778x2511-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/b02ba65577a71425832cc4b8a5452b301e2f17fb-3778x2511.jpg"}},"publishedAt":"2025-06-30T00:00:00.000Z","slug":{"_type":"slug","current":"a-deep-dive-into-nvidia-newton"},"title":"With Great Physics Comes Great Responsibility: A Deep Dive into NVIDIA Newton"},{"_id":"blogPost-setting-up-strapi-cms-on-aws-with-terraform","author":{"name":"Jerrish Varghese","photo":{"asset":{"_id":"image-ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450.jpg"}}},"category":"Cloud","excerpt":"Deploy a modern, scalable Strapi headless CMS on AWS using Terraform for full infrastructure automation. This comprehensive guide covers VPC setup, EC2 configuration, RDS database, S3 storage, and complete Strapi installation with security best practices and cost optimization strategies.","featuredImage":{"alt":"Setting Up a Strapi CMS on AWS with Terraform: A Complete Guide","asset":{"_id":"image-cce2970d7557c16e237284fce4c57417f30a2a36-3778x2511-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/cce2970d7557c16e237284fce4c57417f30a2a36-3778x2511.jpg"}},"publishedAt":"2025-06-20T00:00:00.000Z","slug":{"_type":"slug","current":"setting-up-strapi-cms-on-aws-with-terraform"},"title":"Setting Up a Strapi CMS on AWS with Terraform: A Complete Guide"},{"_id":"blogPost-playwright-uncovered-advanced-strategies-for-web-application-testing","author":{"name":"AryaKrishna AB","photo":null},"category":"Engineering","excerpt":"In the world of modern web development, ensuring that your application works seamlessly across multiple browsers and devices is paramount. Discover advanced Playwright strategies to unlock the full potential of your web application testing workflows and ensure flawless user experiences.","featuredImage":{"alt":"Playwright Uncovered: Advanced Strategies for Web Application Testing","asset":{"_id":"image-9c5b409fb3f4a82f6b392930cd5dd7f7aeafe00a-3778x2511-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/9c5b409fb3f4a82f6b392930cd5dd7f7aeafe00a-3778x2511.jpg"}},"publishedAt":"2025-06-11T00:00:00.000Z","slug":{"_type":"slug","current":"playwright-uncovered-advanced-strategies-for-web-application-testing"},"title":"Playwright Uncovered: Advanced Strategies for Web Application Testing"},{"_id":"blogPost-extracting-fields-from-graph-data-using-rdflib","author":{"name":"Aneesha Sadath","photo":null},"category":"Engineering","excerpt":"Struggling to manage complex, interconnected data? Discover how RDFLib, a powerful Python library for RDF data processing, can transform your graph-based data modeling workflows. Learn to extract specific fields using SPARQL queries and understand when to choose RDF over traditional JSON-based approaches.","featuredImage":{"alt":"Extracting Fields from Graph Data Using RDFLib","asset":{"_id":"image-d95af4d41822c0dd1084d072554728b85b41d620-3778x2511-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/d95af4d41822c0dd1084d072554728b85b41d620-3778x2511.jpg"}},"publishedAt":"2025-05-27T00:00:00.000Z","slug":{"_type":"slug","current":"extracting-fields-from-graph-data-using-rdflib"},"title":"Extracting Fields from Graph Data Using RDFLib"},{"_id":"blogPost-creating-indexes-on-750-million-rows-in-postgresql","author":{"name":"Jerrish Varghese","photo":{"asset":{"_id":"image-ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450.jpg"}}},"category":"Engineering","excerpt":"Creating indexes on massive tables in PostgreSQL can be a performance game-changer—but only if done right. In this post, we explore how to safely and efficiently create a unique index on a 750 million-row table in an AWS RDS environment, while monitoring its progress using built-in PostgreSQL tools.","featuredImage":{"alt":"Creating Indexes on 750 Million Rows in PostgreSQL","asset":{"_id":"image-5a76ff6b0e394fcdde0c7dcf39857dba5a65946b-680x452-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/5a76ff6b0e394fcdde0c7dcf39857dba5a65946b-680x452.jpg"}},"publishedAt":"2025-05-12T00:00:00.000Z","slug":{"_type":"slug","current":"creating-indexes-on-750-million-rows-in-postgresql"},"title":"Creating Indexes on 750 Million Rows in PostgreSQL"},{"_id":"blogPost-zustand-vs-redux-why-simplicity-wins-in-modern-react-state-management","author":{"name":"Sharath Vijayan Nair","photo":null},"category":"Engineering","excerpt":"Zustand and Redux are two influential libraries in the world of React state management. While Redux has long been the industry standard with its robust but often verbose setup, Zustand has recently gained popularity for its minimalist and developer-friendly approach. Developers new to building modern React applications often face the challenge of choosing between these two options. Likewise, teams working on new or evolving projects find themselves weighing simplicity against established patterns. In this blog, we explore the Zustand vs Redux debate in depth, comparing their philosophies, implementations, and performance to help you decide which solution best fits your React development needs in 2025.","featuredImage":{"alt":"Zustand vs. Redux: Why Simplicity Wins in Modern React State Management","asset":{"_id":"image-96e2f936cd2021c05fd4128eb142a5c29858ab09-680x452-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/96e2f936cd2021c05fd4128eb142a5c29858ab09-680x452.jpg"}},"publishedAt":"2025-04-28T00:00:00.000Z","slug":{"_type":"slug","current":"zustand-vs-redux-why-simplicity-wins-in-modern-react-state-management"},"title":"Zustand vs. Redux: Why Simplicity Wins in Modern React State Management"},{"_id":"blogPost-deploying-postgresql-on-kubernetes-with-nodeport","author":{"name":"Ashish Sharma","photo":null},"category":"Engineering","excerpt":"A comprehensive, step-by-step guide to deploying PostgreSQL on Kubernetes with NodePort, featuring detailed Helm installation procedures, configuration strategies, and troubleshooting techniques for common deployment challenges. Learn how to set up PostgreSQL, pgAdmin, and implement best practices with practical solutions for potential networking, resource, and connectivity issues.","featuredImage":{"alt":"Deploying PostgreSQL on Kubernetes with NodePort: A Complete Guide","asset":{"_id":"image-019cff67495e48954a73e05ce58f06acd5f33163-680x452-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/019cff67495e48954a73e05ce58f06acd5f33163-680x452.jpg"}},"publishedAt":"2025-04-18T00:00:00.000Z","slug":{"_type":"slug","current":"deploying-postgresql-on-kubernetes-with-nodeport"},"title":"Deploying PostgreSQL on Kubernetes with NodePort: A Complete Guide"},{"_id":"blogPost-all-hands-meetup-march-2025","author":{"name":"Sachin Biju","photo":null},"category":"Recreation","excerpt":"EDSTEM Unite 2025, held on March 22, 2025, brought together the entire team for a day of learning and celebration. The event featured technical sessions by Eby Augustine on backend technologies and Faize Ahamed Khan on frontend optimization. CTO Jerrish Issac Varghese shared insights from The Pragmatic Programmer. A competitive hackathon awarded ₹5 Lakhs in prizes, with Team Polymorphs winning first place. The day included an awards ceremony recognizing 17 outstanding employees, team-building activities like cricket and boating, and concluded with an inspirational speech from Mithun Madhavan and a celebratory dinner.","featuredImage":{"alt":"EDSTEM Unite 2025 - All Hands Meetup","asset":{"_id":"image-4cc680810e11b01794326b280e3f5c456154bd96-2125x1413-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/4cc680810e11b01794326b280e3f5c456154bd96-2125x1413.jpg"}},"publishedAt":"2025-04-11T00:00:00.000Z","slug":{"_type":"slug","current":"all-hands-meetup-march-2025"},"title":"EDSTEM Unite 2025 - All Hands Meetup"},{"_id":"blogPost-deploying-open-search-and-kafka-on-kubernetes","author":{"name":"Ashish Sharma","photo":null},"category":"Engineering","excerpt":"A comprehensive, step-by-step guide to deploying OpenSearch and Kafka on Kubernetes, featuring detailed Helm installation procedures, configuration strategies, and troubleshooting techniques for common deployment challenges. Learn how to set up OpenSearch, OpenSearch Dashboards, Kafka, and Kafdrop with practical solutions for potential networking, resource, and connectivity issues.","featuredImage":{"alt":"Deploying OpenSearch and Kafka (Kafdrop) on Kubernetes","asset":{"_id":"image-31eb3993725d3e0ff9c4dacd4ada1100b5165338-680x452-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/31eb3993725d3e0ff9c4dacd4ada1100b5165338-680x452.jpg"}},"publishedAt":"2025-03-25T00:00:00.000Z","slug":{"_type":"slug","current":"deploying-open-search-and-kafka-on-kubernetes"},"title":"Deploying OpenSearch and Kafka (Kafdrop) on Kubernetes"},{"_id":"blogPost-ecld-offsite-training-and-workstation","author":{"name":"Sharath Vijayan Nair","photo":null},"category":"Recreation","excerpt":"Edstem Technologies recently organized an ECLD (Edstem Continuous Learning and Development) Offsite Training and Workation, a comprehensive week-long program set in the serene hills of Vagamon. This immersive experience empowered newly joined software engineers with essential communication skills through structured workshops on active listening, group discussions, and presentation techniques. The program followed a carefully designed curriculum spanning three days of focused training, followed by an exploratory day in Vagamon and a team-building campfire night. This initiative reflects Edstem's commitment to cultivating a robust learning culture that equips fresh talent with both technical expertise and professional communication skills necessary for long-term career success.","featuredImage":{"alt":"ECLD Offsite: Empowering Fresh Talent Through Immersive Learning","asset":{"_id":"image-22274bb71c8278634f2f369940c0756099add6b6-680x452-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/22274bb71c8278634f2f369940c0756099add6b6-680x452.jpg"}},"publishedAt":"2025-03-11T00:00:00.000Z","slug":{"_type":"slug","current":"ecld-offsite-training-and-workstation"},"title":"ECLD Offsite: Empowering Fresh Talent Through Immersive Learning"},{"_id":"blogPost-optimizing-web-performance-part-1","author":{"name":"Faiz Ahmed Khan","photo":null},"category":"Engineering","excerpt":"In the digital age, web performance is the cornerstone of user satisfaction and business success. Slow-loading websites don't just test user patience—they directly impact conversion rates, user engagement, and brand credibility. This comprehensive guide delves deep into the art and science of web performance optimization, offering developers and businesses a roadmap to create blazing-fast, responsive web applications. From understanding critical metrics like Core Web Vitals to implementing advanced network optimization techniques, this guide transforms web performance from a technical challenge into a strategic advantage.","featuredImage":{"alt":"Optimizing Web Performance: Faster User Experiences – Part 1","asset":{"_id":"image-1ef83de3cc78ce7d3ce1b8813c94114489e63cd7-2125x1413-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/1ef83de3cc78ce7d3ce1b8813c94114489e63cd7-2125x1413.jpg"}},"publishedAt":"2025-02-20T00:00:00.000Z","slug":{"_type":"slug","current":"optimizing-web-performance-part-1"},"title":"Optimizing Web Performance: Faster User Experiences – Part 1"},{"_id":"blogPost-document-parsing-data-pipeline-using-apache-kafka","author":{"name":"Sangeeta Saha","photo":{"asset":{"_id":"image-097f66c9015bdf2ba08f5783967aef2e43caf865-450x450-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/097f66c9015bdf2ba08f5783967aef2e43caf865-450x450.jpg"}}},"category":"Engineering","excerpt":"In today's world there are many use cases where we need to extract information from files. It could be medical bills submitted to HR, where total amount claimed can be verified against the employee's name. Or a billing system which can calculate billing amounts for each vendor by processing the bills. Also resume processing, where all important information about a candidate can be extracted and matched against job requirements. Automating the above process greatly improves its efficiency and scalability. It can be done by creating a Document Parser Data Pipeline. Here files can be input and data from these files will be read, verified, and stored in some data storage.","featuredImage":{"alt":"Document Parser Data Pipeline using Apache Kafka","asset":{"_id":"image-a5cd7bfe9568b518ac05d02616e9be9ddd7083e5-2125x1413-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/a5cd7bfe9568b518ac05d02616e9be9ddd7083e5-2125x1413.jpg"}},"publishedAt":"2025-02-10T00:00:00.000Z","slug":{"_type":"slug","current":"document-parsing-data-pipeline-using-apache-kafka"},"title":"Document Parser Data Pipeline using Apache Kafka"},{"_id":"blogPost-using-aws-bedrock-for-claudemind-plugin-in-intellij-ides","author":null,"category":"Engineering","excerpt":"Learn how to use AWS Bedrock to power the ClaudeMind plugin in IntelliJ IDEs while ensuring data privacy and enterprise security. This guide walks you through setting up Claude 3.5 Sonnet on AWS Bedrock, deploying a FastAPI proxy, and configuring ClaudeMind to connect to your local API instead of Anthropic's public API. By following this approach, you keep your source code secure, reduce costs with pay-per-use AI, and enable enterprise-ready AI solutions. Perfect for AI software engineers and AI-powered development teams looking to integrate conversational AI into their workflow. ","featuredImage":{"alt":"Using AWS Bedrock for ClaudeMind Plugin in IntelliJ IDEs","asset":{"_id":"image-26a38bbd838153cf26bc50fe78c6d151a57c8764-2125x1413-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/26a38bbd838153cf26bc50fe78c6d151a57c8764-2125x1413.jpg"}},"publishedAt":"2025-01-30T00:00:00.000Z","slug":{"_type":"slug","current":"using-aws-bedrock-for-claudemind-plugin-in-intellij-ides"},"title":"Using AWS Bedrock for ClaudeMind Plugin in IntelliJ IDEs"},{"_id":"blogPost-automating-email-templates-with-aws-ses","author":{"name":"Sharath Vijayan Nair","photo":null},"category":"Engineering","excerpt":"This blog provides a comprehensive guide to automating email templates using AWS SES, Python Flask, and Jinja2. It covers setting up dynamic HTML templates, integrating user details from AWS Cognito, and generating personalized email content. The guide includes an API for fetching email templates, best practices for secure email handling, and enterprise-grade features like MIME formatting, template versioning, and error logging. Additionally, it details email composition and sending through AWS SES, ensuring scalable, cloud-native email automation. Security considerations and best practices make this a robust solution for enterprise applications.","featuredImage":{"alt":"Cloud Native Email Automation with AWS SES, Python, Flask, and Jinja2","asset":{"_id":"image-0f913d1c57a1e2cbd909344a78259219db169d06-680x452-png","url":"https://cdn.sanity.io/images/ygstncxq/production/0f913d1c57a1e2cbd909344a78259219db169d06-680x452.png"}},"publishedAt":"2025-01-23T00:00:00.000Z","slug":{"_type":"slug","current":"automating-email-templates-with-aws-ses"},"title":"Cloud Native Email Automation with AWS SES, Python, Flask, and Jinja2"},{"_id":"blogPost-orchestrating-async-workflows-aws","author":{"name":"Sharath Vijayan Nair","photo":null},"category":"Engineering","excerpt":"In modern microservices architecture, handling asynchronous workflows is a critical requirement for scalability and modularity. This blog will walk you through setting up a microservice architecture where.","featuredImage":{"alt":"Orchestrating Async Workflows with AWS Step Functions and Flask","asset":{"_id":"image-2d31fdfba19a98db719af590f8c194640472f391-680x452-png","url":"https://cdn.sanity.io/images/ygstncxq/production/2d31fdfba19a98db719af590f8c194640472f391-680x452.png"}},"publishedAt":"2025-01-16T00:00:00.000Z","slug":{"_type":"slug","current":"orchestrating-async-workflows-aws"},"title":"Orchestrating Async Workflows with AWS Step Functions and Flask"},{"_id":"blogPost-deploying-running-app-s3-cloudfront","author":{"name":"Ashish Sharma","photo":null},"category":"Engineering","excerpt":"This blog provides a comprehensive guide on how to deploy and host a web application on AWS using a private S3 bucket and CloudFront, leveraging Terraform for infrastructure automation. The private S3 bucket securely stores your application files, while CloudFront acts as a Content Delivery Network (CDN) to serve your application globally with low latency.","featuredImage":{"alt":"Deploying and Running an App on S3 and CloudFront Using Terraform","asset":{"_id":"image-6099192526fb0b5b665dc93d40f0ba9b984dc5b0-680x452-png","url":"https://cdn.sanity.io/images/ygstncxq/production/6099192526fb0b5b665dc93d40f0ba9b984dc5b0-680x452.png"}},"publishedAt":"2025-01-02T00:00:00.000Z","slug":{"_type":"slug","current":"deploying-running-app-s3-cloudfront"},"title":"Deploying and Running an App on S3 and CloudFront Using Terraform"},{"_id":"blogPost-edstem-dinner-grand-hyatt","author":{"name":"Sachin Biju","photo":null},"category":"Recreation","excerpt":"Edstem marked this festive season with an unforgettable Christmas celebration dinner at Grand Hyatt Kochi Bolgatty.The event was a perfect blend of happiness, inspiration, and togetherness, making it a memorable experience for all. ","featuredImage":{"alt":"Christmas Celebration Dinner at Grand Hyatt Kochi Bolgatty","asset":{"_id":"image-59d1d107cd6cdcf991d07c5ce82003651f5c8504-1417x942-png","url":"https://cdn.sanity.io/images/ygstncxq/production/59d1d107cd6cdcf991d07c5ce82003651f5c8504-1417x942.png"}},"publishedAt":"2024-12-21T00:00:00.000Z","slug":{"_type":"slug","current":"edstem-dinner-grand-hyatt"},"title":"Christmas Celebration Dinner at Grand Hyatt Kochi Bolgatty"},{"_id":"blogPost-test-containers","author":{"name":"Jerrish Varghese","photo":{"asset":{"_id":"image-ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450.jpg"}}},"category":"Engineering","excerpt":"At EDSTEM, we've made significant strides in improving our testing infrastructure by adopting Testcontainers as our go-to solution for managing test dependencies. This adoption has transformed how we approach integration testing and has brought newfound reliability to our test suites.","featuredImage":{"alt":"Using Testcontainers - Revolutionizing Our Test Infrastructure","asset":{"_id":"image-9955d3e22dd79e07152ad2ba755301d6196cb6ad-1417x942-png","url":"https://cdn.sanity.io/images/ygstncxq/production/9955d3e22dd79e07152ad2ba755301d6196cb6ad-1417x942.png"}},"publishedAt":"2024-11-18T00:00:00.000Z","slug":{"_type":"slug","current":"test-containers"},"title":"Using Testcontainers - Revolutionizing Our Test Infrastructure"},{"_id":"blogPost-secrets-management-with-sops","author":{"name":"Jerrish Varghese","photo":{"asset":{"_id":"image-ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450.jpg"}}},"category":"Engineering","excerpt":"In the world of modern software development, managing secrets securely while maintaining automation and developer productivity is a constant challenge. At Edstem Technologies, we've found Mozilla's SOPS (Secrets OPerationS) to be an invaluable tool in our security arsenal. Here's how we use SOPS to strike the perfect balance between security and automation.","featuredImage":{"alt":"Secure Secrets Management - Our Journey with SOPS","asset":{"_id":"image-ff52bbecee8b7a0a670dcf5bca595a3ac12222c2-1417x942-png","url":"https://cdn.sanity.io/images/ygstncxq/production/ff52bbecee8b7a0a670dcf5bca595a3ac12222c2-1417x942.png"}},"publishedAt":"2024-11-15T00:00:00.000Z","slug":{"_type":"slug","current":"secrets-management-with-sops"},"title":"Secure Secrets Management - Our Journey with SOPS"},{"_id":"blogPost-llm-responses-rag","author":{"name":"Jerrish Varghese","photo":{"asset":{"_id":"image-ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450.jpg"}}},"category":"Engineering","excerpt":"Retrieval-Augmented Generation (RAG) has revolutionized how we build AI-powered applications at Edstem Technologies. What started as an experiment to improve our LLM responses has evolved into a cornerstone of our technology stack, fundamentally changing how we deliver reliable AI solutions to our users.","featuredImage":{"alt":"Optimizing LLM Responses - Our Journey with RAG","asset":{"_id":"image-688ffb167f91d2d2a60b83d3dea16306c1b1d478-1417x942-png","url":"https://cdn.sanity.io/images/ygstncxq/production/688ffb167f91d2d2a60b83d3dea16306c1b1d478-1417x942.png"}},"publishedAt":"2024-11-13T00:00:00.000Z","slug":{"_type":"slug","current":"llm-responses-rag"},"title":"Optimizing LLM Responses - Our Journey with RAG"},{"_id":"blogPost-k9s-kubernetes-cluster-management","author":{"name":"Jerrish Varghese","photo":{"asset":{"_id":"image-ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450.jpg"}}},"category":"Engineering","excerpt":"In the ever-evolving landscape of Kubernetes management tools, K9s has emerged as a game-changer, offering a powerful terminal-based user interface (TUI) that simplifies cluster operations. Let's dive into how K9s is revolutionizing the way DevOps teams interact with Kubernetes clusters.","featuredImage":{"alt":"K9s - Transforming Kubernetes Cluster Management with a Modern TUI","asset":{"_id":"image-5aec801f36649b54db13e6093a5c37b1d6c1c243-1417x942-png","url":"https://cdn.sanity.io/images/ygstncxq/production/5aec801f36649b54db13e6093a5c37b1d6c1c243-1417x942.png"}},"publishedAt":"2024-11-08T00:00:00.000Z","slug":{"_type":"slug","current":"k9s-kubernetes-cluster-management"},"title":"K9s - Transforming Kubernetes Cluster Management with a Modern TUI"},{"_id":"blogPost-bruno-replacing-postman","author":{"name":"Jerrish Varghese","photo":{"asset":{"_id":"image-ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450.jpg"}}},"category":"Engineering","excerpt":"Tired of juggling API collections across repositories and wrestling with cloud sync? So were we. When our team made the bold decision to switch from Postman to Bruno, a Git-first API client, we discovered a solution that not only solved our immediate challenges but revolutionized our entire development workflow. Here's our journey and why it might be relevant for your team too.","featuredImage":{"alt":"Ditching Postman - Why We Embraced Bruno for API Testing","asset":{"_id":"image-5018384642bdcf1d326a513bdc2e66c9c6aa8268-1417x942-png","url":"https://cdn.sanity.io/images/ygstncxq/production/5018384642bdcf1d326a513bdc2e66c9c6aa8268-1417x942.png"}},"publishedAt":"2024-11-04T00:00:00.000Z","slug":{"_type":"slug","current":"bruno-replacing-postman"},"title":"Ditching Postman - Why We Embraced Bruno for API Testing"},{"_id":"blogPost-aws-sdk-v2-v3-in-node-lambda","author":{"name":"Ashish Sharma","photo":null},"category":"Engineering","excerpt":"Upgrading from AWS SDK v2 to v3 in a Node.js Lambda function can bring significant benefits, such as improved performance and smaller package sizes. AWS SDK v3 is fully modular, meaning you import only the packages you need, which leads to faster cold starts and more efficient Lambda execution.This guide will walk you through the process of upgrading your Lambda function, including automating the conversion process using a bash script.","featuredImage":{"alt":"Migrating from AWS SDK v2 to v3 in Node.js AWS Lambda Functions","asset":{"_id":"image-84176c1bac219b9a8bcdf2f6a77d9d9d946e4f67-1417x942-png","url":"https://cdn.sanity.io/images/ygstncxq/production/84176c1bac219b9a8bcdf2f6a77d9d9d946e4f67-1417x942.png"}},"publishedAt":"2024-08-14T00:00:00.000Z","slug":{"_type":"slug","current":"aws-sdk-v2-v3-in-node-lambda"},"title":"Migrating from AWS SDK v2 to v3 in Node.js AWS Lambda Functions"},{"_id":"blogPost-vite-bundle-visualizer","author":{"name":"Jerrish Varghese","photo":{"asset":{"_id":"image-ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450.jpg"}}},"category":"Engineering","excerpt":"As a frontend engineer, optimizing your application’s performance is always a top priority. One of the key aspects of performance is the size of your JavaScript bundle. The smaller and more efficient your bundle, the faster your app loads and runs. This is where tools like Vite Bundle Visualizer come into play, offering deep insights into your bundle’s composition.","featuredImage":{"alt":"Understanding Vite Bundle Visualizer: A Frontend Engineer’s Guide","asset":{"_id":"image-b0024edde1102e354a443787fdf154445c77be4f-1417x942-png","url":"https://cdn.sanity.io/images/ygstncxq/production/b0024edde1102e354a443787fdf154445c77be4f-1417x942.png"}},"publishedAt":"2024-08-12T00:00:00.000Z","slug":{"_type":"slug","current":"vite-bundle-visualizer"},"title":"Understanding Vite Bundle Visualizer: A Frontend Engineer’s Guide"},{"_id":"blogPost-unleash-feature-flags","author":{"name":"Jerrish Varghese","photo":{"asset":{"_id":"image-ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450.jpg"}}},"category":"Engineering","excerpt":"In the fast-paced world of software development, agility and control are paramount. As businesses strive to deliver continuous value to their users, the ability to manage features dynamically becomes crucial. This is where feature management comes into play, allowing teams to control the release of new features, experiment with different variations, and manage risks without redeploying their applications. One of the most compelling tools in this domain is **Unleash**—an open-source feature management platform that empowers developers and product teams alike. In this blog, we will explore how Unleash can be integrated into your tech stack, enabling you to manage feature flags effectively and efficiently.","featuredImage":{"alt":"Unleash the Power of Feature Management in Your Applications","asset":{"_id":"image-09faea0ce9e5afc74f51f7c34aec0c1f4aac5e3d-1417x942-png","url":"https://cdn.sanity.io/images/ygstncxq/production/09faea0ce9e5afc74f51f7c34aec0c1f4aac5e3d-1417x942.png"}},"publishedAt":"2024-08-09T00:00:00.000Z","slug":{"_type":"slug","current":"unleash-feature-flags"},"title":"Unleash the Power of Feature Management in Your Applications"},{"_id":"blogPost-json-vs-jsonb","author":{"name":"Jerrish Varghese","photo":{"asset":{"_id":"image-ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450.jpg"}}},"category":"Engineering","excerpt":"As backend developers, we often deal with data structures that are both complex and dynamic. JSON has become a ubiquitous format for data exchange due to its flexibility and ease of use. When working with PostgreSQL, you have the option to store JSON data in two different formats: `json` and `jsonb`. While they might seem similar on the surface, the choice between them can have significant implications on performance and storage. In this blog post, we'll explore the differences between `json` and `jsonb` and help you decide which one is better suited for your application.","featuredImage":{"alt":"json vs jsonb in PostgreSQL: Key Differences for Developers","asset":{"_id":"image-c05fa6f7a78bf847bc4e7a3a27bd136338c815f0-1417x942-png","url":"https://cdn.sanity.io/images/ygstncxq/production/c05fa6f7a78bf847bc4e7a3a27bd136338c815f0-1417x942.png"}},"publishedAt":"2024-08-07T00:00:00.000Z","slug":{"_type":"slug","current":"json-vs-jsonb"},"title":"json vs jsonb in PostgreSQL: Key Differences for Developers"},{"_id":"blogPost-implementing-rbac-springboot","author":{"name":"Jerrish Varghese","photo":{"asset":{"_id":"image-ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450.jpg"}}},"category":"Engineering","excerpt":"As a software architect, one of the most critical aspects of designing a robust system is ensuring proper access control. Recently, I had the opportunity to work on a comprehensive municipal management system that required a sophisticated Role-Based Access Control (RBAC) implementation. In this blog post, I'll walk you through our approach to designing and implementing RBAC using Spring Boot 3.3, sharing insights and best practices we discovered along the way.","featuredImage":{"alt":"Implementing RBAC in Spring Boot for a Municipal Management System","asset":{"_id":"image-39fd293448b4ada1353c9886e30263d3321e9bd8-1417x942-png","url":"https://cdn.sanity.io/images/ygstncxq/production/39fd293448b4ada1353c9886e30263d3321e9bd8-1417x942.png"}},"publishedAt":"2024-08-05T00:00:00.000Z","slug":{"_type":"slug","current":"implementing-rbac-springboot"},"title":"Implementing RBAC in Spring Boot for a Municipal Management System"},{"_id":"blogPost-database-iam-access","author":{"name":"Jerrish Varghese","photo":{"asset":{"_id":"image-ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450.jpg"}}},"category":"Engineering","excerpt":"In today's cloud-driven world, securing access to your databases is paramount. If you're using Amazon Web Services (AWS) Relational Database Service (RDS), you might be wondering how to grant read access to your team members without relying on traditional password-based logins. Enter IAM database authentication – a robust, secure, and manageable solution that integrates seamlessly with AWS Identity and Access Management (IAM).","featuredImage":{"alt":"Secure Database Access: Leveraging IAM Authentication for AWS RDS","asset":{"_id":"image-243dc9c0ad4079f6897560fb59301cf2a0e293b0-1417x942-png","url":"https://cdn.sanity.io/images/ygstncxq/production/243dc9c0ad4079f6897560fb59301cf2a0e293b0-1417x942.png"}},"publishedAt":"2024-08-01T00:00:00.000Z","slug":{"_type":"slug","current":"database-iam-access"},"title":"Secure Database Access: Leveraging IAM Authentication for AWS RDS"},{"_id":"blogPost-index-state-management","author":{"name":"Ashish Sharma","photo":null},"category":"Engineering","excerpt":"Managing the lifecycle of data stored in AWS OpenSearch is critical for maintaining performance and controlling costs. For logs and other time-series data, it's often necessary to delete old data after a certain period. In this blog post, we’ll walk through how to set up an Index State Management (ISM) policy to automatically delete data older than 60 days, how to automate this process for new indices using ISM templates, and how to set up monitoring and alerts to ensure everything is working as expected.","featuredImage":{"alt":"Automating Data Retention in AWS OpenSearch with ISM","asset":{"_id":"image-c5283475923f7257441c8682266e9fc51ce48345-1417x942-png","url":"https://cdn.sanity.io/images/ygstncxq/production/c5283475923f7257441c8682266e9fc51ce48345-1417x942.png"}},"publishedAt":"2024-06-20T00:00:00.000Z","slug":{"_type":"slug","current":"index-state-management"},"title":"Automating Data Retention in AWS OpenSearch with ISM"},{"_id":"blogPost-angular-one-login","author":{"name":"Ashish Sharma","photo":null},"category":"Engineering","excerpt":"Integrating OneLogin with an Angular application streamlines the authentication process and enhances security. This blog post delves into setting up the OneLogin environment, crafting essential Angular services, and implementing secure token handling with interceptors. We'll also explore how to authenticate requests on the backend.","featuredImage":{"alt":"Integrating OneLogin with an Angular Application","asset":{"_id":"image-8b9693316537ded1597c0eea130afe73b7841710-1417x942-png","url":"https://cdn.sanity.io/images/ygstncxq/production/8b9693316537ded1597c0eea130afe73b7841710-1417x942.png"}},"publishedAt":"2024-06-17T00:00:00.000Z","slug":{"_type":"slug","current":"angular-one-login"},"title":"Integrating OneLogin with an Angular Application"},{"_id":"blogPost-kafdrop-ubuntu-ec2-instance-ssl","author":{"name":"Ashish Sharma","photo":null},"category":"Engineering","excerpt":"Setting up a reliable and user-friendly interface to manage your Kafka cluster is crucial for efficient data streaming operations. Kafdrop provides a web UI for viewing Kafka topics and managing consumer groups. In thpis guide, we'll demonstrate how to deploy Kafdrop on an Ubuntu EC2 instance with SSL configuration for secure communication. To streamline the process, we'll also provide a Terraform configuration to automate the setup.","featuredImage":{"alt":"Setting Up Kafdrop on Ubuntu EC2 Instance with SSL Configuration","asset":{"_id":"image-02f59ce0997a1d51ab980d25a9992a1814bde625-1417x942-png","url":"https://cdn.sanity.io/images/ygstncxq/production/02f59ce0997a1d51ab980d25a9992a1814bde625-1417x942.png"}},"publishedAt":"2024-06-14T00:00:00.000Z","slug":{"_type":"slug","current":"kafdrop-ubuntu-ec2-instance-ssl"},"title":"Setting Up Kafdrop on Ubuntu EC2 Instance with SSL Configuration"},{"_id":"blogPost-junit-coverage-lombok","author":{"name":"Jerrish Varghese","photo":{"asset":{"_id":"image-ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450.jpg"}}},"category":"Engineering","excerpt":"When working with Java microservices, ensuring high code coverage is crucial for maintaining code quality and reliability. However, if you are using Lombok to reduce boilerplate code, you might encounter a challenge: Lombok-generated methods can skew your code coverage reports, making it seem like you have less coverage than you actually do.","featuredImage":{"alt":"Exclude Lombok-Generated Methods from Jacoco Coverage Reports","asset":{"_id":"image-197a18d6e04f2c4fb12276ec083570076e1bd18a-1417x942-png","url":"https://cdn.sanity.io/images/ygstncxq/production/197a18d6e04f2c4fb12276ec083570076e1bd18a-1417x942.png"}},"publishedAt":"2024-06-03T00:00:00.000Z","slug":{"_type":"slug","current":"junit-coverage-lombok"},"title":"Exclude Lombok-Generated Methods from Jacoco Coverage Reports"},{"_id":"blogPost-aws-oidc-service-account","author":{"name":"Jerrish Varghese","photo":{"asset":{"_id":"image-ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450.jpg"}}},"category":"Engineering","excerpt":"Amazon EKS (Elastic Kubernetes Service) integrates seamlessly with AWS IAM to provide fine-grained access control for your Kubernetes workloads. One of the key components to enable this integration is the IAM OIDC identity provider. In this blog post, we will walk you through the steps to verify whether an OIDC identity provider for your EKS cluster is already created and how to create one if it doesn’t exist.","featuredImage":{"alt":"Check and Create an OIDC Provider for Your AWS EKS Cluster","asset":{"_id":"image-c4f72486adb140f063320caa9cf6334444cc7393-1417x942-png","url":"https://cdn.sanity.io/images/ygstncxq/production/c4f72486adb140f063320caa9cf6334444cc7393-1417x942.png"}},"publishedAt":"2024-05-16T00:00:00.000Z","slug":{"_type":"slug","current":"aws-oidc-service-account"},"title":"Check and Create an OIDC Provider for Your AWS EKS Cluster"},{"_id":"blogPost-spring-read-write-ds","author":{"name":"Jerrish Varghese","photo":{"asset":{"_id":"image-ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450.jpg"}}},"category":"Engineering","excerpt":"In modern software development, achieving optimal performance and scalability often involves separating read and write operations. This separation allows each operation type to be independently optimized and scaled. In this blog post, we'll explore how to implement separate read and write DataSources in a Spring Boot application using Spring Data JPA and AWS Aurora Serverless PostgreSQL.","featuredImage":{"alt":"Separating Read and Write DataSources in Spring Boot","asset":{"_id":"image-4549dc35e5c842e47e082fe5764bd5c32a79ba21-1417x942-png","url":"https://cdn.sanity.io/images/ygstncxq/production/4549dc35e5c842e47e082fe5764bd5c32a79ba21-1417x942.png"}},"publishedAt":"2024-05-03T00:00:00.000Z","slug":{"_type":"slug","current":"spring-read-write-ds"},"title":"Separating Read and Write DataSources in Spring Boot"},{"_id":"blogPost-aws-waf-rate-limiting","author":{"name":"Aravind Sankar","photo":null},"category":"Engineering","excerpt":"In this blog, we will explore how to implement rate limiting for specific URLs using AWS WAFv2. We'll walk through the process of setting up a rate-based rule to protect your application endpoints from excessive requests, ensuring better security and performance.","featuredImage":{"alt":"Implementing Rate Limiting for Specific URLs Using AWS WAFv2","asset":{"_id":"image-2c6be85d60bf540ad79c4c25443dc271677020ec-1417x942-png","url":"https://cdn.sanity.io/images/ygstncxq/production/2c6be85d60bf540ad79c4c25443dc271677020ec-1417x942.png"}},"publishedAt":"2024-05-01T00:00:00.000Z","slug":{"_type":"slug","current":"aws-waf-rate-limiting"},"title":"Implementing Rate Limiting for Specific URLs Using AWS WAFv2"},{"_id":"blogPost-mvn-third-party-jar","author":{"name":"Jerrish Varghese","photo":{"asset":{"_id":"image-ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450.jpg"}}},"category":"Engineering","excerpt":"In the world of Java development, we often find ourselves working with third-party libraries that aren't available in public Maven repositories. Today, we'll explore how to publish these closed-source JAR files to GitHub Packages and use them in other Maven projects.","featuredImage":{"alt":"Publishing Third-Party JARs to GitHub Packages: A Maven Guide","asset":{"_id":"image-ad140d105a07e3c2ebef0fc3a96f6d7fb09b1870-1417x942-png","url":"https://cdn.sanity.io/images/ygstncxq/production/ad140d105a07e3c2ebef0fc3a96f6d7fb09b1870-1417x942.png"}},"publishedAt":"2024-04-26T00:00:00.000Z","slug":{"_type":"slug","current":"mvn-third-party-jar"},"title":"Publishing Third-Party JARs to GitHub Packages: A Maven Guide"},{"_id":"blogPost-aws-subdomain-hosted-zone","author":{"name":"Aravind Sankar","photo":null},"category":"Engineering","excerpt":"When managing DNS records with AWS Route 53, you might encounter scenarios where you need to create a subdomain hosted zone in a separate AWS account. This can be useful for delegating DNS management for a subdomain to another team or ensuring isolation between different environments. In this blog, we’ll walk through the steps to achieve this setup.","featuredImage":{"alt":"Setting Up a Subdomain Hosted Zone in a Different AWS Account","asset":{"_id":"image-a82838e55723c0f36691977f20182f9e5fd8eea4-1417x942-png","url":"https://cdn.sanity.io/images/ygstncxq/production/a82838e55723c0f36691977f20182f9e5fd8eea4-1417x942.png"}},"publishedAt":"2024-04-24T00:00:00.000Z","slug":{"_type":"slug","current":"aws-subdomain-hosted-zone"},"title":"Setting Up a Subdomain Hosted Zone in a Different AWS Account"},{"_id":"blogPost-react-hook-form","author":{"name":"Sangeeta Saha","photo":{"asset":{"_id":"image-097f66c9015bdf2ba08f5783967aef2e43caf865-450x450-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/097f66c9015bdf2ba08f5783967aef2e43caf865-450x450.jpg"}}},"category":"Engineering","excerpt":"Creating a form within React application involves numerous steps and can be quite tedious if it is a complex one. We need to manage the state (both initial state and changes made by user), validations and form submission.","featuredImage":{"alt":"Creating Forms using React Hook Form and Yup","asset":{"_id":"image-a5ece32ac2a54668f07619e94eb208a101c3d256-1417x942-png","url":"https://cdn.sanity.io/images/ygstncxq/production/a5ece32ac2a54668f07619e94eb208a101c3d256-1417x942.png"}},"publishedAt":"2024-04-22T00:00:00.000Z","slug":{"_type":"slug","current":"react-hook-form"},"title":"Creating Forms using React Hook Form and Yup"},{"_id":"blogPost-azue-ad-saml-auth-for-opensearch","author":{"name":"Ashish Sharma","photo":null},"category":"Engineering","excerpt":"Configuring SAML authentication with Azure AD in OpenSearch is a pivotal step towards enhancing both the security and usability of log management systems. By seamlessly integrating these technologies, organizations can ensure secure access to critical data while streamlining user authentication processes.","featuredImage":{"alt":"Achieving Seamless SAML Authentication with Azure AD in OpenSearch","asset":{"_id":"image-47faef8831d33a4f35219998bfad9be6a75a0de6-1417x942-png","url":"https://cdn.sanity.io/images/ygstncxq/production/47faef8831d33a4f35219998bfad9be6a75a0de6-1417x942.png"}},"publishedAt":"2024-04-19T00:00:00.000Z","slug":{"_type":"slug","current":"azue-ad-saml-auth-for-opensearch"},"title":"Achieving Seamless SAML Authentication with Azure AD in OpenSearch"},{"_id":"blogPost-eks-pod-logs-opensearch-configuration","author":{"name":"Ashish Sharma","photo":null},"category":"Engineering","excerpt":"Navigating the dynamic landscape of cloud computing demands meticulous attention to two pivotal aspects: efficient log management and fortified access security. With Kubernetes-based applications, especially on AWS EKS, the need for robust logging solutions becomes paramount. Integrating EKS pod logs with OpenSearch presents a compelling solution for comprehensive log aggregation and analysis. This guide offers a concise walkthrough for setting up EKS pod logs on OpenSearch.","featuredImage":{"alt":"Enabling EKS Pod Logs on OpenSearch","asset":{"_id":"image-27b1b4e34a9558f0aa3dc4a5ba74814886026100-1417x942-png","url":"https://cdn.sanity.io/images/ygstncxq/production/27b1b4e34a9558f0aa3dc4a5ba74814886026100-1417x942.png"}},"publishedAt":"2024-04-18T00:00:00.000Z","slug":{"_type":"slug","current":"eks-pod-logs-opensearch-configuration"},"title":"Enabling EKS Pod Logs on OpenSearch"},{"_id":"blogPost-mock-service-worker-development-testing","author":{"name":"Sangeeta Saha","photo":{"asset":{"_id":"image-097f66c9015bdf2ba08f5783967aef2e43caf865-450x450-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/097f66c9015bdf2ba08f5783967aef2e43caf865-450x450.jpg"}}},"category":"Engineering","excerpt":"Very often, the frontend team starts their work, and the backend APIs are still not ready. Instead of waiting for APIs to be completed, frontend developer can use Mock Service Worker (MSW) to create mock Request Handlers. MSW will intercept network requests of the application. On finding a matching Request Handler, it will provide a mock response as configured by the developer. Mock responses can be configured in detail to mimic an actual API response very closely. Once the backend APIs are completed, developers can replace the mock API URL with the actual one.","featuredImage":{"alt":"Mock Service Worker for Development and Testing","asset":{"_id":"image-e035ab1b9557e83520b3b5d1d942765d2ff6f851-1417x942-png","url":"https://cdn.sanity.io/images/ygstncxq/production/e035ab1b9557e83520b3b5d1d942765d2ff6f851-1417x942.png"}},"publishedAt":"2024-04-16T00:00:00.000Z","slug":{"_type":"slug","current":"mock-service-worker-development-testing"},"title":"Mock Service Worker for Development and Testing"},{"_id":"blogPost-authentication-using-msal","author":{"name":"Sangeeta Saha","photo":{"asset":{"_id":"image-097f66c9015bdf2ba08f5783967aef2e43caf865-450x450-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/097f66c9015bdf2ba08f5783967aef2e43caf865-450x450.jpg"}}},"category":"Engineering","excerpt":"Authentication and providing secure access to users is an integral part of any web application. We can either build it on our own or use a third-party service such as the Microsoft Authentication Library (MSAL). This not only saves development effort and resources but also provides us with a reliable, efficient, and time-tested solution.","featuredImage":{"alt":"Authentication Using Microsoft Authentication Library (MSAL)","asset":{"_id":"image-a743eb0ff4228eadd073034ced0ba214ace8ae2e-1417x942-png","url":"https://cdn.sanity.io/images/ygstncxq/production/a743eb0ff4228eadd073034ced0ba214ace8ae2e-1417x942.png"}},"publishedAt":"2024-04-15T00:00:00.000Z","slug":{"_type":"slug","current":"authentication-using-msal"},"title":"Authentication Using Microsoft Authentication Library (MSAL)"},{"_id":"blogPost-micro-frontend-single-spa-qiankun","author":{"name":"Sangeeta Saha","photo":{"asset":{"_id":"image-097f66c9015bdf2ba08f5783967aef2e43caf865-450x450-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/097f66c9015bdf2ba08f5783967aef2e43caf865-450x450.jpg"}}},"category":"Engineering","excerpt":"The Micro frontend architecture allows us to divide a web application into individual applications working loosely together. Each application, also known as a micro frontend, is an independent smaller module of the web application that can be build and run independently. These can be developed using different frameworks, allowing companies to leverage the expertise of team members specializing in different technologies.","featuredImage":{"alt":"Micro Frontend using Single SPA and Qiankun","asset":{"_id":"image-0b85f3ab3ae940367b08ec342639d4792afec8a5-1417x942-png","url":"https://cdn.sanity.io/images/ygstncxq/production/0b85f3ab3ae940367b08ec342639d4792afec8a5-1417x942.png"}},"publishedAt":"2024-04-09T00:00:00.000Z","slug":{"_type":"slug","current":"micro-frontend-single-spa-qiankun"},"title":"Micro Frontend using Single SPA and Qiankun"},{"_id":"blogPost-driving-automated-cost-optimization-aws","author":{"name":"Ashish Sharma","photo":null},"category":"Engineering","excerpt":"In the ever-evolving landscape of cloud computing, optimizing costs while maintaining operational efficiency is a top priority for businesses leveraging Amazon Web Services (AWS). Among the plethora of strategies available, harnessing automation to manage resources effectively stands out as a cornerstone for sustainable cost optimization. In this blog post, we'll delve into distinct approaches for cost-saving measures tailored to RDS and EC2 instances in AWS infrastructure, employing AWS Lambda, Amazon EventBridge, and Terraform.","featuredImage":{"alt":"AWS Cost Optimization: Automating RDS and EC2 Instance Management","asset":{"_id":"image-87521aea0248c7d64941583a8647cfbfacf21964-1417x942-png","url":"https://cdn.sanity.io/images/ygstncxq/production/87521aea0248c7d64941583a8647cfbfacf21964-1417x942.png"}},"publishedAt":"2024-04-05T00:00:00.000Z","slug":{"_type":"slug","current":"driving-automated-cost-optimization-aws"},"title":"AWS Cost Optimization: Automating RDS and EC2 Instance Management"},{"_id":"blogPost-streamlining-web-testing-selenium-with-sauce-labs","author":{"name":"AryaKrishna","photo":null},"category":"Engineering","excerpt":"In the realm of software development, ensuring the quality and reliability of web applications is paramount. Manual testing, while essential, can be time-consuming and prone to human error. That's where automated testing tools like Selenium and cloud-based testing platforms like Sauce Labs come into play. In this blog post, we'll explore the seamless integration of Selenium with Sauce Labs and how this powerful combination streamlines web testing processes.","featuredImage":{"alt":"Streamlining Web Testing: Integrating Selenium with Sauce Labs","asset":{"_id":"image-f7475228e0870361115774f06982a5d108f1a65d-1417x942-png","url":"https://cdn.sanity.io/images/ygstncxq/production/f7475228e0870361115774f06982a5d108f1a65d-1417x942.png"}},"publishedAt":"2024-04-02T00:00:00.000Z","slug":{"_type":"slug","current":"streamlining-web-testing-selenium-with-sauce-labs"},"title":"Streamlining Web Testing: Integrating Selenium with Sauce Labs"},{"_id":"blogPost-azure-blob-storage-secure-file-access","author":{"name":"Sangeeta Saha","photo":{"asset":{"_id":"image-097f66c9015bdf2ba08f5783967aef2e43caf865-450x450-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/097f66c9015bdf2ba08f5783967aef2e43caf865-450x450.jpg"}}},"category":"Engineering","excerpt":"Uploading files and images are an essential part of most web applications. There are","featuredImage":{"alt":"Securely Upload and Fetch Files in Azure Blob via SAS Token","asset":{"_id":"image-0de4ee7ede9438e0002a99ae50bad10d4bf2287f-1417x942-png","url":"https://cdn.sanity.io/images/ygstncxq/production/0de4ee7ede9438e0002a99ae50bad10d4bf2287f-1417x942.png"}},"publishedAt":"2024-03-13T00:00:00.000Z","slug":{"_type":"slug","current":"azure-blob-storage-secure-file-access"},"title":"Securely Upload and Fetch Files in Azure Blob via SAS Token"},{"_id":"blogPost-empowering-women-empowering-futures","author":{"name":"Sachin Biju","photo":null},"category":"Recreation","excerpt":"On International Women's Day, we celebrate the inspiring women of Edstem who are shaping the future of technology. Their stories are testaments to their perseverance, ingenuity, and dedication, fueled by the supportive environment we foster at Edstem.","featuredImage":{"alt":"Empowering Women, Empowering Futures - Inspiring Women's Journeys","asset":{"_id":"image-e50d522d9917cfad000c913481f84d9f72822143-2125x1413-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/e50d522d9917cfad000c913481f84d9f72822143-2125x1413.jpg"}},"publishedAt":"2024-03-08T00:00:00.000Z","slug":{"_type":"slug","current":"empowering-women-empowering-futures"},"title":"Empowering Women, Empowering Futures - Inspiring Women's Journeys"},{"_id":"blogPost-optimizing-aws-eks-costs-terraform","author":{"name":"Ashish Sharma","photo":null},"category":"Engineering","excerpt":"In today's cloud-driven landscape, optimizing costs while maintaining operational efficiency is paramount. Amazon Elastic Kubernetes Service (EKS) offers a powerful platform for container orchestration, but without proper management, costs can quickly escalate. In this guide, we'll explore how to leverage Terraform to optimize costs in AWS EKS by implementing various strategies, including the automation of Horizontal Pod Autoscaling (HPA) and Cluster Autoscaler.","featuredImage":{"alt":"Optimizing AWS EKS Costs with Terraform: A Comprehensive Guide","asset":{"_id":"image-ed3261a08234fb8220e4432c0ab7010bbbb7ba2a-1417x942-png","url":"https://cdn.sanity.io/images/ygstncxq/production/ed3261a08234fb8220e4432c0ab7010bbbb7ba2a-1417x942.png"}},"publishedAt":"2024-03-01T00:00:00.000Z","slug":{"_type":"slug","current":"optimizing-aws-eks-costs-terraform"},"title":"Optimizing AWS EKS Costs with Terraform: A Comprehensive Guide"},{"_id":"blogPost-java-vs-python-which-reigns-supreme","author":{"name":"Christina Antony","photo":null},"category":"Engineering","excerpt":"Python and Java stand out as prominent programming languages widely utilized in today's software development landscape. While Java has maintained its position as a longstanding and extensively utilized programming language, Python has experienced notable popularity growth in recent times. Individuals venturing into the field of software development often struggle with the genuine question of whether to opt for Java or Python. Similarly, those embarking on new projects face the dilemma of choosing between Python and Java. So in this blog, we are going to dive a bit deeper into this Python Vs Java rivalry and analyze it from various perspectives.","featuredImage":{"alt":"Java vs Python: Which Programming Language Reigns Supreme?","asset":{"_id":"image-2883f0cc345824b2c800bb459e6f4da31f9ba6e1-1417x942-png","url":"https://cdn.sanity.io/images/ygstncxq/production/2883f0cc345824b2c800bb459e6f4da31f9ba6e1-1417x942.png"}},"publishedAt":"2024-02-21T00:00:00.000Z","slug":{"_type":"slug","current":"java-vs-python-which-reigns-supreme"},"title":"Java vs Python: Which Programming Language Reigns Supreme?"},{"_id":"blogPost-index-as-a-unique-constraint-pros-and-cons","author":{"name":"Eby Augustine","photo":null},"category":"Engineering","excerpt":"In database management systems, ensuring data integrity is paramount. One common approach to enforcing uniqueness in a relational database is by using unique constraints. However, unique constraints can be implemented using indexes as well. In this blog post, we'll delve into the advantages and disadvantages of using an index as a unique constraint, with a focus on practical considerations and implications for database design and performance.","featuredImage":{"alt":"Index as a Unique Constraint: Pros and Cons in Databases","asset":{"_id":"image-9a3ab11dc9551e87a8ab8d13cc8501673152364f-1417x942-png","url":"https://cdn.sanity.io/images/ygstncxq/production/9a3ab11dc9551e87a8ab8d13cc8501673152364f-1417x942.png"}},"publishedAt":"2024-02-12T00:00:00.000Z","slug":{"_type":"slug","current":"index-as-a-unique-constraint-pros-and-cons"},"title":"Index as a Unique Constraint: Pros and Cons in Databases"},{"_id":"blogPost-navigating-complex-aggregations-in-amazon-opensearch-with-java","author":{"name":"Jerrish Varghese","photo":{"asset":{"_id":"image-ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450.jpg"}}},"category":"Engineering","excerpt":"In the realm of data analytics, the ability to efficiently aggregate and analyze data can uncover valuable insights that drive strategic decision-making. Amazon OpenSearch Service, building upon the powerful features of Elasticsearch, offers robust capabilities for handling complex data operations. This blog post delves into executing complex aggregations on an OpenSearch index and demonstrates how to process these results using Java, focusing on integration within a Spring Boot application using Spring Data Elasticsearch.","featuredImage":{"alt":"Navigating Complex Aggregations in Amazon OpenSearch with Java","asset":{"_id":"image-d1f954aa3ea08dee3ef490d22cbc3f9c9f6dedf4-1417x942-png","url":"https://cdn.sanity.io/images/ygstncxq/production/d1f954aa3ea08dee3ef490d22cbc3f9c9f6dedf4-1417x942.png"}},"publishedAt":"2024-02-05T00:00:00.000Z","slug":{"_type":"slug","current":"navigating-complex-aggregations-in-amazon-opensearch-with-java"},"title":"Navigating Complex Aggregations in Amazon OpenSearch with Java"},{"_id":"blogPost-kafka-topic-config-management","author":{"name":"Jerrish Varghese","photo":{"asset":{"_id":"image-ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450.jpg"}}},"category":"Engineering","excerpt":"Managing Apache Kafka topic configurations can be a tedious task, especially when dealing with a large number of topics across multiple clusters. One common requirement is adjusting the retention period of topics to control how long messages are stored. In this blog, we'll explore how to automate this process using Python, with a focus on Amazon MSK (Managed Streaming for Apache Kafka), though the concepts can be applied to any Kafka setup. Additionally, we'll discuss how to skip specific topics based on naming conventions, such as internal Kafka topics or topics with specific keywords.","featuredImage":{"alt":"Automating Kafka Topic Configuration Management with Python","asset":{"_id":"image-06b3e2d2212d43ea397ca385c4ec73af75736348-1417x942-png","url":"https://cdn.sanity.io/images/ygstncxq/production/06b3e2d2212d43ea397ca385c4ec73af75736348-1417x942.png"}},"publishedAt":"2024-01-31T00:00:00.000Z","slug":{"_type":"slug","current":"kafka-topic-config-management"},"title":"Automating Kafka Topic Configuration Management with Python"},{"_id":"blogPost-identifying-hanging-queries-in-postgresql","author":{"name":"Jerrish Varghese","photo":{"asset":{"_id":"image-ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450.jpg"}}},"category":"Engineering","excerpt":"Dealing with long-running queries is a common challenge for database administrators and developers. Long-running queries can consume significant resources, slow down the database performance, and impact the overall user experience. Fortunately, PostgreSQL offers tools to identify and manage these queries efficiently. In this blog post, we'll guide you through the steps to identify long-running queries in your PostgreSQL database and how to safely terminate them if necessary.","featuredImage":{"alt":"How to Identify and Kill Long-Running Queries in PostgreSQL","asset":{"_id":"image-20774f574417f8cd16660c267941967f05a70337-1417x942-png","url":"https://cdn.sanity.io/images/ygstncxq/production/20774f574417f8cd16660c267941967f05a70337-1417x942.png"}},"publishedAt":"2024-01-22T00:00:00.000Z","slug":{"_type":"slug","current":"identifying-hanging-queries-in-postgresql"},"title":"How to Identify and Kill Long-Running Queries in PostgreSQL"},{"_id":"blogPost-feature-toggles-in-spring","author":{"name":"Jerrish Varghese","photo":{"asset":{"_id":"image-ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450.jpg"}}},"category":"Engineering","excerpt":"In the ever-evolving landscape of software development, the ability to quickly adapt features without redeployment is invaluable. Feature toggles, or feature flags, offer an elegant solution to this challenge, allowing developers to enable or disable features dynamically. This blog post will explore a generic approach to implementing feature toggles in Spring Boot applications using Spring Profiles and Configuration Properties.","featuredImage":{"alt":"Implementing Dynamic Feature Toggles in Spring Boot","asset":{"_id":"image-2f1dc126fbb14a3601cb463a1a1f79436f9242e4-1417x942-png","url":"https://cdn.sanity.io/images/ygstncxq/production/2f1dc126fbb14a3601cb463a1a1f79436f9242e4-1417x942.png"}},"publishedAt":"2024-01-16T00:00:00.000Z","slug":{"_type":"slug","current":"feature-toggles-in-spring"},"title":"Implementing Dynamic Feature Toggles in Spring Boot"},{"_id":"blogPost-dynamic-data-querying-duckdb-aws-lambda","author":{"name":"Jerrish Varghese","photo":{"asset":{"_id":"image-ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450.jpg"}}},"category":"Engineering","excerpt":"In the world of serverless computing, AWS Lambda has emerged as a powerful solution for running code in response to triggers without the need to provision or manage servers. Combining Lambda with DuckDB, an in-process SQL database, opens up intriguing possibilities for data-intensive applications. This article delves into a practical scenario where Lambda and DuckDB are leveraged to execute SQL queries dynamically based on incoming requests, showcasing flexibility and efficiency in data handling.","featuredImage":{"alt":"Streamlining AWS Lambda with DuckDB for Dynamic Data Handling","asset":{"_id":"image-417e98b76f21c2b4dab5d76a0a673055bf7c3e15-1417x942-png","url":"https://cdn.sanity.io/images/ygstncxq/production/417e98b76f21c2b4dab5d76a0a673055bf7c3e15-1417x942.png"}},"publishedAt":"2024-01-08T00:00:00.000Z","slug":{"_type":"slug","current":"dynamic-data-querying-duckdb-aws-lambda"},"title":"Streamlining AWS Lambda with DuckDB for Dynamic Data Handling"},{"_id":"blogPost-kafka-retry-mechanism-with-spring-kafka","author":{"name":"Eby Augustine","photo":null},"category":"Engineering","excerpt":"Kafka is a distributed streaming platform widely used for building real-time data pipelines and streaming applications. However, in distributed systems, failures are inevitable. Handling failures gracefully is crucial to ensure data integrity and system reliability. One of the critical aspects of building resilient Kafka applications is implementing a robust retry mechanism.","featuredImage":{"alt":"Kafka Retry Mechanism in Spring Kafka","asset":{"_id":"image-a003fa119f6b21fb6312900f9d40c758e434a021-1417x942-png","url":"https://cdn.sanity.io/images/ygstncxq/production/a003fa119f6b21fb6312900f9d40c758e434a021-1417x942.png"}},"publishedAt":"2024-01-04T00:00:00.000Z","slug":{"_type":"slug","current":"kafka-retry-mechanism-with-spring-kafka"},"title":"Kafka Retry Mechanism in Spring Kafka"},{"_id":"blogPost-redis-response-caching-springboot","author":{"name":"Jerrish Varghese","photo":{"asset":{"_id":"image-ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450.jpg"}}},"category":"Engineering","excerpt":"Optimizing API performance is always crucial for delivering exceptional user experiences. One effective strategy to achieve this goal is response caching, where frequently requested responses are stored and served directly from the cache. Redis, a lightning-fast in-memory data store, serves as an excellent caching solution. In this blog post, we'll explore how we leveraged Redis Cache Manager in a Spring Boot application to implement response caching effectively for a huge list of master data specific endpoints that had heavy traffic in production environment. Additionally, we'll introduce a sample Plain Old Java Object (POJO) called `Lookup` and the `Office` class to illustrate seamless integration with our caching mechanism.","featuredImage":{"alt":"Optimizing Performance with Redis Response Caching in Spring Boot","asset":{"_id":"image-a878dd2d8bcef33ecc949c53ace6757e966154ff-1417x942-png","url":"https://cdn.sanity.io/images/ygstncxq/production/a878dd2d8bcef33ecc949c53ace6757e966154ff-1417x942.png"}},"publishedAt":"2023-12-26T00:00:00.000Z","slug":{"_type":"slug","current":"redis-response-caching-springboot"},"title":"Optimizing Performance with Redis Response Caching in Spring Boot"},{"_id":"blogPost-leveraging-github-actions-scheduled-workflows","author":{"name":"Jerrish Varghese","photo":{"asset":{"_id":"image-ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450.jpg"}}},"category":"Engineering","excerpt":"Automation plays a pivotal role in continuous integration and deployment by streamlining software development processes. GitHub Actions, a powerful feature of GitHub, enables developers to automate workflows directly within their repositories. While GitHub Actions are commonly associated with triggers like pushes, pull requests, and issue creation, they also offer a scheduling feature that allows workflows to execute at specific times. In this blog post, we'll delve into leveraging GitHub Actions for scheduled workflows.","featuredImage":{"alt":"Leveraging GitHub Actions for Scheduled Workflows","asset":{"_id":"image-9b4dd937ff58054b292790adcd76eae807e94c9f-1417x942-png","url":"https://cdn.sanity.io/images/ygstncxq/production/9b4dd937ff58054b292790adcd76eae807e94c9f-1417x942.png"}},"publishedAt":"2023-12-20T00:00:00.000Z","slug":{"_type":"slug","current":"leveraging-github-actions-scheduled-workflows"},"title":"Leveraging GitHub Actions for Scheduled Workflows"},{"_id":"blogPost-jwt-tokens-microservice-architectures-spring-cloud","author":{"name":"Jerrish Varghese","photo":{"asset":{"_id":"image-ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450.jpg"}}},"category":"Engineering","excerpt":"In modern microservice architectures, ensuring secure communication between services is a critical concern. This often involves the propagation of JWT (JSON Web Token) tokens for authentication and authorization purposes. Today, we'll dive into a specific scenario: a user management service (`UserService`) needs to fetch data from a profile management service (`ProfileService`), using JWT for secure communication.","featuredImage":{"alt":"Secure JWT Propagation in Microservices with Spring Cloud","asset":{"_id":"image-2be61fe5fbc3fcacce0e012f6a47e2032a6edbe8-1417x942-png","url":"https://cdn.sanity.io/images/ygstncxq/production/2be61fe5fbc3fcacce0e012f6a47e2032a6edbe8-1417x942.png"}},"publishedAt":"2023-12-13T00:00:00.000Z","slug":{"_type":"slug","current":"jwt-tokens-microservice-architectures-spring-cloud"},"title":"Secure JWT Propagation in Microservices with Spring Cloud"},{"_id":"blogPost-postgres-copy-command-for-rapid-data-migration","author":{"name":"Jerrish Varghese","photo":{"asset":{"_id":"image-ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450.jpg"}}},"category":"Engineering","excerpt":"When faced with the challenge of migrating large datasets into a PostgreSQL database, efficiency and speed are paramount. Traditional row-by-row insertion methods, while straightforward, can be painfully slow, turning data migration tasks into lengthy ordeals. However, by leveraging PostgreSQL's powerful `COPY` command, we can dramatically reduce migration times — from tens of minutes to under a minute, even for substantial datasets.","featuredImage":{"alt":"Harnessing the Power of PostgreSQL's COPY Command for Rapid Data Migration","asset":{"_id":"image-642cc1348e525621b29ec6876c6d9710e6bd00d8-1417x942-png","url":"https://cdn.sanity.io/images/ygstncxq/production/642cc1348e525621b29ec6876c6d9710e6bd00d8-1417x942.png"}},"publishedAt":"2023-11-07T00:00:00.000Z","slug":{"_type":"slug","current":"postgres-copy-command-for-rapid-data-migration"},"title":"Harnessing the Power of PostgreSQL's COPY Command for Rapid Data Migration"},{"_id":"blogPost-knowledge-sharing-culture","author":{"name":"Aravind Sankar","photo":null},"category":"Engineering","excerpt":"A knowledge sharing culture is not just about disseminating information, but rather creating an environment where learning becomes a natural part of the company's DNA. At Edstem, we understand the significance of cultivating such a culture, especially for our freshers. Through our dedicated department, **Edstem Continuous Learning and Development (ECLD)**, we're committed to creating an enriched learning environment that empowers both newcomers and seasoned professionals to excel and stay ahead in the dynamic world of technology.","featuredImage":{"alt":"Knowledge Sharing Culture – Cultivating a Learning Environment for Freshers","asset":{"_id":"image-ff3987e72427c41df7af11ce0dd76c111eeaa1c4-680x452-png","url":"https://cdn.sanity.io/images/ygstncxq/production/ff3987e72427c41df7af11ce0dd76c111eeaa1c4-680x452.png"}},"publishedAt":"2023-09-22T00:00:00.000Z","slug":{"_type":"slug","current":"knowledge-sharing-culture"},"title":"Knowledge Sharing Culture – Cultivating a Learning Environment for Freshers"},{"_id":"blogPost-edstem-onam-aug-2023","author":{"name":"Biju PS","photo":null},"category":"Recreation","excerpt":"The young, vibrant and energetic team of Edstem Technologies came together for a spectacular event filled with buzzing celebrations. The event is not only a day of fun and bonding but showcases the core of unity and camaraderie that defines the Edstem family. As the golden rays of the sunbathed the peaceful landscape, the day promised a blend of traditional celebrations and amazing team-building activities, creating memories to be cherished forever.","featuredImage":{"alt":"Onam Celebration Team Meetup: A Day of Joy, Unity, and Celebration","asset":{"_id":"image-fe27b4ba730a8ebdd79bdd11c4ea877686072763-680x452-png","url":"https://cdn.sanity.io/images/ygstncxq/production/fe27b4ba730a8ebdd79bdd11c4ea877686072763-680x452.png"}},"publishedAt":"2023-08-31T00:00:00.000Z","slug":{"_type":"slug","current":"edstem-onam-aug-2023"},"title":"Onam Celebration Team Meetup: A Day of Joy, Unity, and Celebration"},{"_id":"blogPost-supercharging-agile-with-restrospectives","author":{"name":"Aravind Sankar","photo":null},"category":"Engineering","excerpt":"Agile methodologies have been nothing short of a revolution in the way software development teams work, emphasizing adaptability,","featuredImage":{"alt":"Supercharging Agile: Harnessing the Benefits of Retrospectives","asset":{"_id":"image-d5ad29b9bbd1a637de2855cdf781fce8853e5b7c-680x452-png","url":"https://cdn.sanity.io/images/ygstncxq/production/d5ad29b9bbd1a637de2855cdf781fce8853e5b7c-680x452.png"}},"publishedAt":"2023-07-14T00:00:00.000Z","slug":{"_type":"slug","current":"supercharging-agile-with-restrospectives"},"title":"Supercharging Agile: Harnessing the Benefits of Retrospectives"},{"_id":"blogPost-jenkins-to-github-actions-guide","author":{"name":"Azhar MA","photo":null},"category":"Engineering","excerpt":"Edstem undertook the task of migrating some complex existing Jenkins CI/CD pipelines of a client to Github actions. This guide aims to share the know-how obtained during the process.","featuredImage":{"alt":"Migrating Jenkins Pipelines to GitHub Actions: A Comprehensive Guide","asset":{"_id":"image-9b8b61d08cc1c26f4d8b9c0776183147563a3f0e-680x452-png","url":"https://cdn.sanity.io/images/ygstncxq/production/9b8b61d08cc1c26f4d8b9c0776183147563a3f0e-680x452.png"}},"publishedAt":"2023-05-30T00:00:00.000Z","slug":{"_type":"slug","current":"jenkins-to-github-actions-guide"},"title":"Migrating Jenkins Pipelines to GitHub Actions: A Comprehensive Guide"},{"_id":"blogPost-leveraging-kubernetes-sidecar","author":{"name":"Jerrish Varghese","photo":{"asset":{"_id":"image-ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450.jpg"}}},"category":"Engineering","excerpt":"In the world of Kubernetes, the sidecar pattern has emerged as a powerful tool for enhancing the functionality and resilience of your applications. This pattern involves running a secondary container alongside the primary application container, allowing you to extend the capabilities of your application without modifying its core logic. In this blog post, we'll explore a real-world example of the sidecar pattern, demonstrating how it can be used to synchronize data from an S3 bucket to a shared volume.","featuredImage":{"alt":"Using Kubernetes Sidecar Pattern for Efficient Data Sync","asset":{"_id":"image-02c33d614ce225b7e125414e5b258a83ea6ce5ca-1417x942-png","url":"https://cdn.sanity.io/images/ygstncxq/production/02c33d614ce225b7e125414e5b258a83ea6ce5ca-1417x942.png"}},"publishedAt":"2023-03-09T00:00:00.000Z","slug":{"_type":"slug","current":"leveraging-kubernetes-sidecar"},"title":"Using Kubernetes Sidecar Pattern for Efficient Data Sync"},{"_id":"blogPost-object-mother-pattern","author":{"name":"Jerrish Varghese","photo":{"asset":{"_id":"image-ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450-jpg","url":"https://cdn.sanity.io/images/ygstncxq/production/ca3c6a9afaefef1d8c0b1e8fcfe8149ee3d6bf80-450x450.jpg"}}},"category":"Engineering","excerpt":"In the realm of software testing, one often faces the challenge of setting up complex objects or object graphs for unit tests. This setup can be cumbersome, repetitive, and clutter the test code, making it hard to understand and maintain. Here, the Object Mother pattern comes to the rescue. It is a testing pattern designed to help construct test fixtures, making tests cleaner and more readable.","featuredImage":{"alt":"Introduction to the Object Mother Pattern in Software Testing","asset":{"_id":"image-a706f83c23ccea6e163ce6d1ea5160d7940f6e44-1417x942-png","url":"https://cdn.sanity.io/images/ygstncxq/production/a706f83c23ccea6e163ce6d1ea5160d7940f6e44-1417x942.png"}},"publishedAt":"2023-01-20T00:00:00.000Z","slug":{"_type":"slug","current":"object-mother-pattern"},"title":"Introduction to the Object Mother Pattern in Software Testing"},{"_id":"blogPost-edstem-meetup-nov-2021","author":{"name":"Thomas Oommen","photo":null},"category":"Recreation","excerpt":"It was a dream come true for Team Edstem**. After a long spell of solitary workspace, the very prospect of camping together for four days was exciting. The old-timers were meeting each other after a considerable gap and many of the freshers were seeing other team members for the first time. It was an occasion they were eagerly looking forward to.","featuredImage":{"alt":"Edstem's 2021 Retreat: Team Bonding Success","asset":{"_id":"image-c38908d6b3a6c66c680ef275e996a0686761e17d-680x452-png","url":"https://cdn.sanity.io/images/ygstncxq/production/c38908d6b3a6c66c680ef275e996a0686761e17d-680x452.png"}},"publishedAt":"2021-12-11T00:00:00.000Z","slug":{"_type":"slug","current":"edstem-meetup-nov-2021"},"title":"Edstem's 2021 Retreat: Team Bonding Success"}]]]
The Micro frontend architecture allows us to divide a web application into individual applications working loosely together. Each application, also known as a micro frontend, is an independent smaller module of the web application that can be build and run independently. These can be developed using different frameworks, allowing companies to leverage the expertise of team members specializing in different technologies.
Micro frontends are to frontend what micro services are to backend. They offer similar benefits like independent management and deployment of each module, reduced conflicts, and better fault isolation. They share the DOM of the application. One micro frontend's DOM should not be touched by another micro frontend, like how one backend microservice's database should not be touched by any microservice except the one that owns/controls it.
As the Micro frontend pattern is gaining popularity, many frameworks have come up that support their development. Some of the more prominent ones are :
Single SPA framework
Bit
Module Federation
Piral Framework
Open Components Framework
In this blog, we will discuss about building micro frontends using the Single SPA framework and Qiankun ( another framework based on Single SPA ). Google Maps and Gmail use the Single SPA framework. Single SPA can be considered as a Javascript router for micro frontends. Here, each individual micro frontend has a life cycle. It can load, mount, and unmount from the DOM based on the application route.
Next, we will discuss the following
Example Application
Building example application using Single SPA
Building example application using Qiankun
1. Example Application
This HR application has features Employee Management, Project Management and Techdesk. Each of these features are built and run as a separate application. It can also be called and run from the main application. Choosing an icon from the left sidebar, redirects to different routes. Depending on the route, corresponding micro frontend is mounted.
1.1 HR Application (Complete web application which calls micro frontends)
As we can see from the images above, the applications can be run independently, as well as from within the HR application. Each of the applications can be developed using a different framework. They can be developed, maintained, and deployed separately by separate teams.
2. Single SPA
Single spa applications consist of a container or root config app and multiple applications. Root config app renders the HTML page and registers the applications. Applications share this HTML page; they do not have their own HTML page. Each application will mount and unmount depending on the activeWhen rule added while registering the application. Following applications will be created for the HR application hr-root hr-sidebar hr-employee hr-project hr-techdesk
2.1 Root App
2.1.1 First we need to install create-single-spa dependency.
Then we can run create-single-spa within the hr-root folder. We should choose the type ‘single spa root config.’ This creates a project with 2 files in src folder.
root-config.js
index.ejs
2.1.2 Applications must be registered in the root-config.js file
The sidebar application will be loaded in the div with id = "sidebar-container" The employee, project and techdesk application will be loaded, one at a time, within the div with id = "app-container"
2.2 Applications
2.2.1 We need to create an application folder for each of the applications. We can then run create-single-spa within each folder. This time we will choose the option "single-spa application/parcel" In framework, we will choose the framework that will be used to build the application. This creates a project with 3 files in src folder. Within the hr-sidebar folder it will create
hr-sidebar.js
root.component.js
root.component.test.js
2.2.2 In the hr-sidebar.js file we need to wrap React, ReactDOM and the root component with single-spa-react (for react application). Similarly, if it is an angular application, it should be wrapped in single-spa-angular and so on. Also, we must export three lifecycle functions, bootstrap, mount and unmount. Bootstrap will be called only once when the child application is initialized, mount will be triggered every time the application is loaded. Unmount is called each time application is unloaded. domElementGetter function is optional and can be used to specify the dom element where the application will be mounted.
javascript
// Code snippet 4 - hr-sidebar.js
import React from "react";
import ReactDOM from "react-dom";
import singleSpaReact from "single-spa-react";
import Root from "./root.component";
const lifecycles = singleSpaReact({
React,
ReactDOM,
rootComponent: Root,
domElementGetter
});
export const { bootstrap, mount, unmount } = lifecycles;
function domElementGetter() {
return document.getElementById("sidebar-container")
}
2.2.3 The root.component.js will have the application content. Here, we can return the App component which has the entire application.
javascript
// Code snippet 5 – root.component.js
import App from './App'
export default function Root(props) {
return <App />;
}
The package.json has scripts for running the application in stand-alone mode or as a micro frontend application.
Once all the applications are setup, we can run the root config application. The other applications will be loaded and depending on the application URL, they will be mounted or unmounted.
Since the hr-sidebar application is active whenever the "/" route is active, it will always be mounted and displayed in element with id = "sidebar-container"
Whenever the employee icon is chosen, application route will be /employee. The hr-employee application will be mounted and displayed in the element with id = "app-container."
Similarly, when project and techdesk icons are chosen, hr-project and hr-techdesk applications are mounted respectively. They will also be displayed in element with id = "app-container."
3. Qiankun
Qiankun is based on single-spa and aims to make the implementation easier.
Qiankun apps consist of a main application and multiple sub applications.
The sub applications are mounted and unmounted based on routes of the main application.
The main application must install qiankun dependency and register the sub applications.
Each sub application needs to export bootstrap, mount, and unmount, three lifecycle hooks, in its own entry javascript file. They also need to add some configuration to the application bundler. This is done so that main application can correctly identify information exposed by sub application.
3.1 Main application
3.1.1 After installing the qiankun dependency, at the entry point of the main application, we should register the sub applications.
javascript
// Code snippet 7 – index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { registerMicroApps, start, setDefaultMountApp } from "qiankun";
import subApps from './sub-apps';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
registerMicroApps(subApps);
setDefaultMountApp("/employee");
start();
Setting of the default app to be mounted is optional.
The microfrontends core team recommends that when we should only work with one micro frontend application in local at a time, rest should be already deployed. The Employee, Project and Techdesk application are already deployed in dev.
3.1.3 However, if we want to test the application before deploying, we can register the applications as below
From the main application whenever we go to the route /employee, employee application will be displayed in the element with id "subapp-container", when we go to route and so on.
The html element with id = "subapp-container" is the area surrounded by blue border.
All sub applications whose activeRule matches the URL being called will be loaded there.
Note: The header and sidebar are part of the main application here.
3.2 Sub Applications
Note: We are considering only sub applications built with webpack (Vue, React, Angular)
For all applications with webpack, publicPath specifies the base path for assets within the application.
To make an application behave as a qiankun sub application, we need to modify the publicPath at runtime, such that it is the one provided by qiankun (i.e. the path of the main application).
3.2.1 We can create file public-path.js within src folder.
3.2.2 Next, we need to import the public-path.js file right at the top of the entry file index.js. We also modify the ReactDOM. render and export the bootstrap, mount, and unmount functions.
Once the above setup is done, we can run the main application. Whenever the employee icon is chosen, it will go to the /employee route, and Employee Management application will run and be displayed in the element with id = "subapp-container."
Similarly, when project and techdesk icons are chosen it will run Project Management and Techdesk applications respectively.
Conclusion
The Micro frontend architecture can benefit teams greatly if they are working on large complex applications. However, careful planning is required to leverage its advantages. All microfrontends within an application should have consistent look and feel. If micro frontends need to communicate with each other, they can use custom props while registering the application. Teams developing different micro frontends need to regularly communicate with each other to prevent component or logic duplication.
Once the above points are taken care of, Micro frontends are a great way to increase efficiency and the turnaround time for adding new features.