{"id":28728,"date":"2025-03-11T18:11:02","date_gmt":"2025-03-11T12:41:02","guid":{"rendered":"https:\/\/blogrevamp.cashfree.com\/?p=28728"},"modified":"2025-03-11T18:14:37","modified_gmt":"2025-03-11T12:44:37","slug":"optimising-concurrency-in-spring-boot","status":"publish","type":"post","link":"https:\/\/blogrevamp.cashfree.com\/optimising-concurrency-in-spring-boot\/","title":{"rendered":"Optimising Concurrency in Spring Boot: Robust Solutions for Scalable Systems"},"content":{"rendered":"<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_81 counter-hierarchy ez-toc-counter ez-toc-custom ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<span class=\"ez-toc-title-toggle\"><a href=\"#\" class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\" aria-label=\"Toggle Table of Content\"><span class=\"ez-toc-js-icon-con\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #005c31;color:#005c31\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #005c31;color:#005c31\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/span><\/a><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/blogrevamp.cashfree.com\/optimising-concurrency-in-spring-boot\/#Problem_Statement\" >Problem Statement<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/blogrevamp.cashfree.com\/optimising-concurrency-in-spring-boot\/#Approaches\" >Approaches<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/blogrevamp.cashfree.com\/optimising-concurrency-in-spring-boot\/#UNIQUE_Constraint\" >UNIQUE Constraint<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/blogrevamp.cashfree.com\/optimising-concurrency-in-spring-boot\/#Redis_Locking\" >Redis Locking<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/blogrevamp.cashfree.com\/optimising-concurrency-in-spring-boot\/#Pessimistic_Locking\" >Pessimistic Locking<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/blogrevamp.cashfree.com\/optimising-concurrency-in-spring-boot\/#Optimistic_Locking\" >Optimistic Locking<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/blogrevamp.cashfree.com\/optimising-concurrency-in-spring-boot\/#Conclusion\" >Conclusion<\/a><\/li><\/ul><\/nav><\/div>\n\n<p class=\"wp-block-paragraph\">Concurrency issues can be tricky as they often arise when multiple requests hit your system at the same time, leading to unexpected behaviour and performance slowdowns. If you\u2019ve ever dealt with race conditions or inconsistent data updates, you know how frustrating it can be. In this article, we break down the complexities of concurrent programming in Spring Boot and explore different strategies to handle them. Let\u2019s dive in!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Problem_Statement\"><\/span>Problem Statement<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Our challenge revolved around managing concurrent requests to our application, where each request was unique and had to be processed, unlike scenarios where idempotency ensures consistency, here, the <strong>distinct nature of each request necessitated special handling<\/strong>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Our objective was to execute an<strong> upsert operation for incoming requests<\/strong>. If an entry exists, update it based on the logic; otherwise, create a new one.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Let\u2019s take a simple example of a school keeping a record of marks scored by students.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Refer to the below schema of \u201c<strong>Students<\/strong>\u201d-<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Problems with this upsert approach &#8211; <\/strong>Initially, the table is in an empty state.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh7-rt.googleusercontent.com\/docsz\/AD_4nXd0uxiLqIAjVRgpp7ZvjzvozCD7FRwpNlbxE8IlUALKR3QOINd02sW3pZUGPBzfnvEUjqoMNpeQck-wmNVh0MkMy4pjYij81sVAzD8XZJud-635LIMTLSdBS2HL7DfkmbTkopr7?key=CjT-ieF3SMf0TJ4MSUpJt9Gc\" alt=\"\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">We received three requests containing the student\u2019s name, subject, and marks scored in that subject.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Aman, English, 95<\/li>\n\n\n\n<li>Aman, Math, 96<\/li>\n\n\n\n<li>Aman, Physics, 98<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Ideal scenario of data entry (If the requests were not concurrent)<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Marks scored in English get added to the Total Marks.<\/li>\n<\/ol>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh7-rt.googleusercontent.com\/docsz\/AD_4nXeNw5lWgy3e9fhoyqBxkNyd_dL8kz_qL1LhS4y1dvTGf3WgStgkbn0Wh00bZsERtckeSPb2api_S5q5LOFMUDdlDL0TwNLHiHicRwz6NsTu2cewZD6cZNpkZT08dW9JxRXCyQVlTg?key=CjT-ieF3SMf0TJ4MSUpJt9Gc\" alt=\"\"\/><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh7-rt.googleusercontent.com\/docsz\/AD_4nXcOX92-p96UMzE9Tfrj_pELRDeW8sSwaboCAUai36p_nVy27A8zUU05zRyWnidJXht-pi3XNgWhjwYmLFUKrCeNeWj2h7tQmUPxYj8CkTFzMLI3_bISUberUfALmSMh4LYD93AEVQ?key=CjT-ieF3SMf0TJ4MSUpJt9Gc\" alt=\"\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">2. Marks scored in Math get added to the Total Marks (<strong>95+96=191<\/strong>)<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh7-rt.googleusercontent.com\/docsz\/AD_4nXcnkR448JkbSZiHrgPaD14ZPS5gG1jYvGAnFp3q9xqGWXthMHpExF5XmNabXG3Hloo1rtXl3_ZahuFOC46UC-PBkJ4s8HU7qQaAjyB_E5_5q--QRLhf_7EP7N8hHfi3H4J2Rd_8?key=CjT-ieF3SMf0TJ4MSUpJt9Gc\" alt=\"\"\/><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh7-rt.googleusercontent.com\/docsz\/AD_4nXeYByt4IecQNHVgz1Jqu0zpJyPrNKIOKCX3ZmU1S6-uiWLUc4fwoz9zvjeSWSgENY2zQw4dzx0_LoBxH5bnfsSCP2RuShZm77IYhioVQD_DUZO7bE_qxaffB2HqGV861107wHrMyQ?key=CjT-ieF3SMf0TJ4MSUpJt9Gc\" alt=\"\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">3. Marks scored in physics get added to the Total Marks (<strong>191+98=289<\/strong>)<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh7-rt.googleusercontent.com\/docsz\/AD_4nXeBDUi5EwJ76RCKidj8B1rynBIYmZavfs3-sl48PZC9WQEiIK0owtab2XmDZRXSmy10kPObTGyWZGs2UsJ1rcrqjump6-rT45k_IxkvFqiQFS3r5eYDEiCCDYDMIdEL33G36DzH?key=CjT-ieF3SMf0TJ4MSUpJt9Gc\" alt=\"\"\/><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh7-rt.googleusercontent.com\/docsz\/AD_4nXfCUomFjpp0hr8QQ5z5pwPba1eraVXwm55e3oTqJQpgG-tKvjMA30cW9YBvnm7gNRP3jdpeHSEZJhrh30DjDoJ4bbWWg-lEhB6n7Px_EcutaFJmyUnh0GJZha5hmZR6z8OtrrYr?key=CjT-ieF3SMf0TJ4MSUpJt9Gc\" alt=\"\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Considering the scenarios where we would have received concurrent requests:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Consider the first 2 requests as concurrent<br>&#8211; Both requests for English and Math find no existing entry, leading to concurrent attempts to create the same student record.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh7-rt.googleusercontent.com\/docsz\/AD_4nXeOog9LgdFYjxZFSv6oojucW4yESSwQXNFciPxWDMgTCsSzmJMlfY-FpvV7Q7hydHa2lNm6KGw1msepCECFZhNGGHwRAxAfqBfFnmepXzhf54aiBdZ83IqOVm25RcPagD9SVeaA2Q?key=CjT-ieF3SMf0TJ4MSUpJt9Gc\" alt=\"\"\/><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh7-rt.googleusercontent.com\/docsz\/AD_4nXe8ub4lusViq3Jd8nSK-zzGX47h4HprwHc4Sv1KgJ4kN2m5W1WoPuE1ENJEqrXcJA6kJ1gVAK55NShnmPB5bs6JFG8LauRE9JwGU--6A2w4kTsqx2mjcEUFJy8ta6Uiltr_4Xo_qg?key=CjT-ieF3SMf0TJ4MSUpJt9Gc\" alt=\"\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&#8211; The 3rd request returns two entries instead of one, causing an. InvalidMethodArgumentException.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>If we had received the 2nd and 3rd requests at the same time.<br>&#8211; Below is the Table state after processing the 1st request-<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh7-rt.googleusercontent.com\/docsz\/AD_4nXesdpvHX38WzZO0dcCMw99c_I7CTY3ceMdPQw9ErbhhWsVhe6YIsiQCrZqrUt7-SzeJxAseJMbUrTGlSaaRhGR5cKhMIs2YnOfl77Q5w-Ck2ObPYrRMpHm9VGa1UiH5tPD05TjS7A?key=CjT-ieF3SMf0TJ4MSUpJt9Gc\" alt=\"\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">&#8211; Both Math and Physics requests fetch the same table entry. Math updates the total marks to 191 (95+96), and Physics updates it to 193 (95+98). Since updates happen sequentially, if Math updates first, the final state will reflect Physics\u2019 marks, as Physics doesn\u2019t re-read the total marks.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh7-rt.googleusercontent.com\/docsz\/AD_4nXczRLWXdEVwwkPOPfwKZTu0zowBnXgvhP43gsOoAkafFzjt02MH12OCqnwXyF0Lj_cGEp8GNSG78J2417HNTCMQDxON1hmmB3pdC_aEtVUWta_kjvcgrqJMerZTA6CZpfTI8z0a?key=CjT-ieF3SMf0TJ4MSUpJt9Gc\" alt=\"\"\/><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh7-rt.googleusercontent.com\/docsz\/AD_4nXeoxwvipaoeV2NswzDEEAHYDJlnIViDN1nA7gwT-H6U5M8h6RTdC0qGvnkNalN6-uV97aNCEuTnJSGLWuhmNu16Xoy6H9jHQHlGnKSjib8hPYShK6JQcrXD2rXIW3kKz2bRpNWT?key=CjT-ieF3SMf0TJ4MSUpJt9Gc\" alt=\"\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">After reading the above examples, you can get a clear picture of what problems one can face with concurrency.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Approaches\"><\/span>Approaches<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Here, we shall discuss some approaches we followed to address this issue. We\u2019ll present code snippets for each approach and discuss their pros and cons.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Unique constraint<\/li>\n\n\n\n<li>Redis locking<\/li>\n\n\n\n<li>Pessimistic locking + Unique key<\/li>\n\n\n\n<li>Optimistic locking + Unique key<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"UNIQUE_Constraint\"><\/span>UNIQUE Constraint<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">We can add a unique key constraint on the table such that no two rows can have the same value for fields marked as <strong>UNIQUE<\/strong>. When a request comes to insert a duplicate row, we get a data violation exception and handle it by doing a retry on getting this exception with backoff delay and max attempts configured.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This not only helps in <strong>data integrity but also improves read performance<\/strong>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Limitation<\/strong>: This solution resolves the duplicate creation of rows in the table, but this will only work when we are <strong>doing an INSERT operation<\/strong> <strong>and not an UPDATE.<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><em>Note:<\/em> <em>You should be careful while adding keys or index on <\/em>the <em>table as it can lead to another impact; for example, in a write-heavy system, it will reduce the overall performance of the system<\/em><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Here, we have used<a href=\"https:\/\/docs.spring.io\/spring-retry\/docs\/api\/current\/\"><strong> <\/strong><strong>Retryable<\/strong><\/a><strong> <\/strong>annotation of spring boot over this API. The delay can be similar to the time the entire functionality takes to complete. Also, set maxAttempts value to avoid infinite retry loops. Don\u2019t forget to use @EnableRetry annotation on the application.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh7-rt.googleusercontent.com\/docsz\/AD_4nXcAGj6bp_qHiDxkdG9vFEp8srG-Z7q5EAEDK2jxffE6jY22_wmuHFON9EP9H_h7AGF3xCwkunDpCI5_NxPPMxuc-9S3u95eggDTwJe7CFMkp3nqOF77ka6ltPximOEjBTKZoej3?key=CjT-ieF3SMf0TJ4MSUpJt9Gc\" alt=\"\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Let\u2019s say we have received three concurrent requests for the same example.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Marks scored in one of the subjects get added to total marks.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh7-rt.googleusercontent.com\/docsz\/AD_4nXeoNHs-lejIxcKAux7rsUMo8W0GVmttXWIVUTMuEkguvnqXHPguM7ElLiomT1Igr-0LZf8BuIXWPh9eDYrZyytk20IGMuOQNxjuORAOAkCdlmDz7_0eOaGj-ivm8WPvTqLZpwJ_oQ?key=CjT-ieF3SMf0TJ4MSUpJt9Gc\" alt=\"\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">For the other two requests, DataIntegrityViolationException would be thrown as there is already one entry with the name Aman. This will lead to a retry for the other two requests.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Now we are facing the same scenario where the last two requests come at the same time, so the request for other subjects will read the existing marks and update the entry to make a total of 191 (96+95), and similarly, the request for Physics will make a total of 194 (96+98). The final state of the table can contain 191 or 194.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh7-rt.googleusercontent.com\/docsz\/AD_4nXfCi-f8ljbC1dQ0G0h1LrO_kNGBXEzewBtqxUSlqcg6L3RORuYxPbem-hw_Xeb1ebEHU8IK4qKjTNaOV84AucPhXvmzwofPxdWlJ-ic-oXh3wHAaciI8CcEOFGKNvxymJzytf7fQg?key=CjT-ieF3SMf0TJ4MSUpJt9Gc\" alt=\"\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Using this approach,<strong> we have resolved the issue where multiple entries were created but the problem of updating in case of concurrent requests still stands.<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">To handle concurrent insertions, adding a unique key to the table is not always possible. So, by leveraging the ACID nature of SQL, we can use a query like this.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh7-rt.googleusercontent.com\/docsz\/AD_4nXchVJMCubcaBDVJk2-bO9RHQO_9bsl3JLgik_7BvpTPhoAWYgSubVyKPLUhOLHP3xtEfMt9lLBitq6X6iXAsNuBmGk3kgm7ccMpFrvxZak1-yUGYOknUDHDQTrAs8h4U8i0iqyIpA?key=CjT-ieF3SMf0TJ4MSUpJt9Gc\" alt=\"\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><em>Note: By adding a select query with insert, the time taken to insert will increase if proper indexing is not present on the table.<\/em><\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Redis_Locking\"><\/span>Redis Locking<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Redis\u2019s single-threaded nature ensures that only one command executes simultaneously, meaning concurrent requests are processed sequentially.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We create a Redis key from the input (e.g., \u2018Aman\u2019), ensuring concurrent requests use the same key.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The RLock interface in Java implements Lock and internally uses a semaphore. Reentrant locks (RLocks) prevent self-deadlocks by allowing the same thread to acquire the lock multiple times, ensuring smooth execution even in nested calls.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh7-rt.googleusercontent.com\/docsz\/AD_4nXeAhCctMhsr1NJe1-htO2n29vemgvu4V066WsPCBRxRQON60jeQ95p9I6ubKP2AwBgcWXIaXUOShWYcKE2_PSxE4HqewKaqlOdBdiqmhlTO9sR0ohqpNoriNUo4Nr22_Ee6HiPTmg?key=CjT-ieF3SMf0TJ4MSUpJt9Gc\" alt=\"\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Let\u2019s discuss the flow with our example by taking a case when we receive two concurrent requests.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Any one of the two concurrent requests will acquire the lock first, as Redis is single-threaded. Let\u2019s say that a request for English acquires the lock first.<br>&#8211; This creates a Redis entry with the key \u2018<strong>Aman\u2019<\/strong> and value <strong>\u2018{lock holder id, count = 1, ttl}\u2019<\/strong>. The lock holder ID uniquely identifies the thread holding the lock.<br>&#8211; The second request tries to acquire the same lock but finds the \u2018<strong>Aman\u2019 <\/strong>key in Redis, so its thread is blocked. The lock can be released in two ways. When the first thread releases lock or if the lock\u2019s TTL (1 second in this case) expires, allow the second request to proceed.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh7-rt.googleusercontent.com\/docsz\/AD_4nXc1taXouJpSePGx_c42UsPgFSrBjTz6pLQpx8M2RLIERTgcwOqrIqoCrJe1CqdKMNcdQgLoX3ApB3OcQb132YKd0FfRBoaWx8bCamcOOVuznIW4aYCYlIz2tjnXIRVyJMYB31-ILw?key=CjT-ieF3SMf0TJ4MSUpJt9Gc\" alt=\"\"\/><\/figure>\n\n\n\n<ul class=\"wp-block-list\">\n<li>When the first thread releases the lock by calling the unlock() function, the Redis key <strong>\u2018Aman\u2019 is deleted once the count reaches zero<\/strong>. It also <strong>publishes an unlock message to the Redis pub\/sub channel<\/strong>, notifying other waiting threads that the lock has been released. This allows the second thread to acquire the lock and proceed through the critical section, just like the first thread.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh7-rt.googleusercontent.com\/docsz\/AD_4nXfB0O8_g0-HGR_BmNYHdhXPYVYEJkxiXH5_dlEfPIJIISKCklp38nDtZSSb8fe8quGHZoEhNvveqPtgLpvRD2MxEXOIGDnfPXV_Ti6elm-DS1duIBFUheg06LMuJXlAK0AprXj9Gw?key=CjT-ieF3SMf0TJ4MSUpJt9Gc\" alt=\"\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Let\u2019s look at the problems with the above approach.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Blocking:<\/strong> If another thread or process already holds a lock, the current thread will block, potentially leading to competition for the resource.<\/li>\n\n\n\n<li><strong>Redis Downtime:<\/strong> Failure to acquire a lock due to Redis being down can result in code blocking unnecessarily.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Non-Blocking Redis Lock\u200a\u2014\u200aTo avoid the above problems we can use an approach to<strong> tryAcquireLock<\/strong>.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh7-rt.googleusercontent.com\/docsz\/AD_4nXfbXjtseIbjfzhfkkIvN2xX4RZQZnYYWKjiCQFc4aM8vIwY3aADk1GikTe7IhKQPBJhDiDKTWpReetNmjh_xfUF9I9IdZ-btjwSkEIuyKQNWD2bzKwwoaRAadpKWJdApajGN9Z8?key=CjT-ieF3SMf0TJ4MSUpJt9Gc\" alt=\"\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Code for Releasing RLock<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh7-rt.googleusercontent.com\/docsz\/AD_4nXeMkWqsnog0CN9cFWAriKDEjsGTP-Q3eXQjaVW8BbxFIkhOTSrmAtw4lxugzT3MJ9Gn1hnneC1o6N2Mag_4V3OTrRsGO50kgE42KPqVNuI8xfpOqDJyiMD6x8qj6gOuW7_eAeDgAg?key=CjT-ieF3SMf0TJ4MSUpJt9Gc\" alt=\"\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><em>Note: To handle the non-blocking nature of tryLock, we will need a retry logic to ensure that all the requests are executed.<\/em><\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Pessimistic_Locking\"><\/span><strong>Pessimistic Locking<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">In this approach, when a transaction accesses a resource (such as a database row), it acquires a lock on that resource. This lock prevents other transactions from accessing or modifying the resource until it is released. <strong>This ensures that only one transaction can modify the resource at a time, thus preventing conflicts and maintaining data integrity<\/strong>.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh7-rt.googleusercontent.com\/docsz\/AD_4nXfeLMfOv5iGSLq2prxPUiHGgX15ESFORpj_yzsxLLbcw7R5oI93csqftboiI4ALKbG6eyxqRZKxv23mCQTy1_7vS4lDYgByHgN6oEmygjTJEPu-E7rOFIvHXE73rbsZKSSeQCzl?key=CjT-ieF3SMf0TJ4MSUpJt9Gc\" alt=\"\"\/><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh7-rt.googleusercontent.com\/docsz\/AD_4nXeZYs7XOWZ2Sy-afp1847O3hJ1yiYdx1B_ZVsvXR0y2UVJHLe1AOkk94Q6uieFq9liBOyG9Zg1e5BR-ur20xl4-IwXp8EVfJ7k8BpokFDhz8dX8QogjC04Qt86sw3jCImmriG2ByQ?key=CjT-ieF3SMf0TJ4MSUpJt9Gc\" alt=\"\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Why are we using @Transactional?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We are performing both read (<em>findByName<\/em>) and write (<em>save<\/em>) operations to the database in <strong>upsertStudentMarks<\/strong> method. Transactional blocks ensure that if any operation fails, the entire transaction is rolled back. A pessimistic lock is tightly coupled with a transaction and is held for the duration of the transaction. Without the transaction, the lock would immediately be released after the query is completed.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Let\u2019s discuss this in detail with our example of 3 concurrent requests.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>All three requests check if the entry with the name is present and don\u2019t find any entry. Remember that pessimistic locking holds a lock on a resource, but the resource (row) is not present yet, so pessimistic locking does not come into the picture now. Assuming that the request for math is processed first, its entry gets created, and for the other two requests, we get SQL error as we use unique key constraints. In such a case, we use a similar retry mechanism as used in our above approach for a unique key constraint.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh7-rt.googleusercontent.com\/docsz\/AD_4nXfR079iDVSjSSNtBGCsQ1nqScywN_QpB078tx0xRLoNxSRBYCyuCKFYbzr5nXc-Tljp2sKnvAx-f-IUaDt58rUA5K6DY8PZxCj1Y7MiBEleIOhI8w_TJ9427aanUr28umEStJ6V1g?key=CjT-ieF3SMf0TJ4MSUpJt9Gc\" alt=\"\"\/><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh7-rt.googleusercontent.com\/docsz\/AD_4nXdUbwyCU7fhZPz1DfUHBWObxTGz1PdOSb18ZiUYlq9T0BTGRSwax8HQIc923PdfVkn5sG_gUbhlEsUdCx1Hl9OuZlFY3pW9nESeEahXA3dtBMgDTkWjDoh-h22qHf-RG8OcwqsRyg?key=CjT-ieF3SMf0TJ4MSUpJt9Gc\" alt=\"\"\/><\/figure>\n\n\n\n<ul class=\"wp-block-list\">\n<li>With pessimistic lock, the <strong><em>findByName<\/em><\/strong> would change to SELECT * from Students where name = ? for UPDATE. This locks the rows as if they are already being updated. Other transactions trying to access these rows are placed in a queue, managed internally by the database, to ensure they are executed in order once the lock is released.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh7-rt.googleusercontent.com\/docsz\/AD_4nXdE-civcEI8A5Akr7ssZ-mCxqDmsj_32M9yEfuYIt05ah8z-GRpfmB2zaB3HB3klEN-iIBwLwv1IYUMRhhfK5qLpH3bPVBAO7o2sZY_7-WTAyB6VMiD4xtI93u7MOq7aKV8ChjQqg?key=CjT-ieF3SMf0TJ4MSUpJt9Gc\" alt=\"\"\/><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh7-rt.googleusercontent.com\/docsz\/AD_4nXfRxjtaxaiwDS0CgmAnBd7KGupWDr_9Bq24i_0LpCa4kCFQQLyWbFitaszuBYS6v61YM8fFlCl3jBTTcgIhqqZ63M4iztqvNhptwRl4Qnv7Dp1GkifC_6fSNSiPLoJs93a3BWFz?key=CjT-ieF3SMf0TJ4MSUpJt9Gc\" alt=\"\"\/><\/figure>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>When the transaction for English is committed, the lock is released,<\/strong> and the SELECT .. for UPDATE query for physics, which was blocked, can now execute. The final table state would look like this.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh7-rt.googleusercontent.com\/docsz\/AD_4nXcQjkmWBUyz3vrH4Ak0xNFvq2GNr04jD8BjzzeONUwSkVmUqMryqMkZFLmORub21c6T-h-HTM95kDC01veiUa-JSCgqhuwpgWDbpIiawKBQRaMCBtfq3ce4YkF48lMwkf1m_RIi?key=CjT-ieF3SMf0TJ4MSUpJt9Gc\" alt=\"\"\/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Optimistic_Locking\"><\/span>Optimistic Locking<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Unlike pessimistic locking, which assumes conflicts will occur and proactively acquires locks, optimistic locking assumes conflicts are rare and <strong>handled only when necessary.<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Versioning or Timestamps:<\/strong> Each database record has a version number or timestamp that tracks its last update.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Read Phase:<\/strong> When a transaction reads a record, it also retrieves its current version number or timestamp.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Validation Phase:<\/strong> Before committing changes, the transaction checks that the version or timestamp hasn\u2019t changed since it was first read. If it matches, the transaction proceeds; if not, it aborts.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Commit Phase:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>If no changes are detected (version\/timestamp matches), the transaction commits.<\/li>\n\n\n\n<li>If changes are detected (version\/timestamp mismatch), the transaction aborts, indicating stale data, and retries the operation.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Minimal Locking Overhead:<\/strong> Optimistic locking reduces the need for locks during the read and update phases, only detecting conflicts at commit time.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh7-rt.googleusercontent.com\/docsz\/AD_4nXfD2WlptNmYWPDBLjQ9bFhFKLRghFhCucf8zJV8XCVd7FB_-wPikqR7zTh9jWITKpsTspjUHr7mMqFeRB_WJFvnmoz8r4OztGlrm81hofYMn64j3_vhutg1uNBwlTgOnVnteXqHdQ?key=CjT-ieF3SMf0TJ4MSUpJt9Gc\" alt=\"\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Here, we are retrying on ObjectOptimisticLockingFailureException<strong>,<\/strong> which occurs when optimistic locking fails. It indicates that another transaction has updated or deleted the same database record the current transaction tries to modify, resulting in a version conflict. Also note that we have increased the maxAttempts because, unlike pessimistic locking, which locks the resource and blocks the other transactions, optimistic locking always tries to update and encounters exceptions whenever it fails. This leads to retry on every concurrent request.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh7-rt.googleusercontent.com\/docsz\/AD_4nXf7o6MFdF6MrV1kbUBlNqVn-NyCpd1v7LPOVQth32vWHd3X1OrHZ-FH5sjAFWrzJs-hQNoev-hGPUAMdaTIkq2nEggEcP9IaP_5QP7BKWASLSMUUk_CgkVp__3NfOxj1C8jA8EY1g?key=CjT-ieF3SMf0TJ4MSUpJt9Gc\" alt=\"\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><em>@OptimisticLocking(type = OptimisticLockType.DIRTY)<\/em> tells Hibernate to use \u201cdirty\u201d optimistic locking, meaning the version is checked only when fields in the entity are actually modified. For this approach, Hibernate generates UPDATE statements that include only the modified fields in the WHERE clause, enabled by the <em>@DynamicUpdate<\/em> annotation.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><em>Note: We can manually implement optimistic locking with a native query like: UPDATE Students SET totalMarks=? WHERE id=? AND totalMarks=?<\/em><strong><em> <\/em><\/strong><em>Instead of relying on annotations.<\/em><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Coming to the explanation with our example of receiving three concurrent requests<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Similar to pessimistic locking, due to the unique key on the name, we encounter <em>DataIntegrityViolationException<\/em> for the two requests that are later served by the database.<\/li>\n\n\n\n<li>The two requests for Physics and English are retried using the <em>@Retryable<\/em>annotation. Both follow the same flow until they reach the update step. The English request attempts to update the total marks to 191 (95+96), while the Physics request tries to update the marks to 194 (98+96).<br>Assume the English update succeeds first, changing the table\u2019s state. The update query for Physics will be <em>UPDATE Students SET totalMarks=194 WHERE id=1 AND totalMarks=96<\/em>. Since the total marks have already changed to 191, this query fails, leading to an ObjectOptimisticLockingFailureException.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh7-rt.googleusercontent.com\/docsz\/AD_4nXeRBRb9OacNPjjUYQGhb4FkF9OKuQDtwOeDKC-LuFSemn6WJrlursy1ZfieP2y5S_3nX9pYGpKzgwwyQFXhbw_kGVdUsahfi9vzGAL3qt8hd2hsa9w9TMUJ-Uj_x22fyjPLGcRtjQ?key=CjT-ieF3SMf0TJ4MSUpJt9Gc\" alt=\"\"\/><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh7-rt.googleusercontent.com\/docsz\/AD_4nXe_Lia1YzbUry9beyrdq5D6BDpv3xjUbyu2wvXmVq6vX7xxux_37_E5hhPtOvWL7nmYDqUDd4gL0Qh1WaGC5qw3PLgiKVheO2j9HzPVdY99jrV9trUp1bt1Zi1ZPzyYQyd9zGWyIQ?key=CjT-ieF3SMf0TJ4MSUpJt9Gc\" alt=\"\"\/><\/figure>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The request for Physics will be retried, and the marks will be updated without issue. Note that our flow is executed 3 times for three concurrent requests<strong>, and it would increase with the increasing number of concurrent requests.<\/strong><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Conclusion\"><\/span>Conclusion<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The following table provides a comparative analysis of Redis Lock, Optimistic Locking, and Pessimistic Locking, highlighting their key differences and best-use scenarios.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh7-rt.googleusercontent.com\/docsz\/AD_4nXcxTqp4AKaNJtYUINBGZrTm9Fcnm9a8UXrD7dtNqQiRNf4PnxBSEyXzxcSt_Tx39WhQ5zI3GF6z-8svttwLzzwkVvf7Syuwkvc0H72w64AYO2qmpRtjWhlSdVWl7vgUnIRk9WFcHw?key=CjT-ieF3SMf0TJ4MSUpJt9Gc\" alt=\"\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">While Redis locking provides a lightweight and efficient mechanism for handling concurrent requests, database-level strategies like pessimistic and optimistic locking ensure data integrity under different use cases. The choice of the best approach depends on system requirements, workload characteristics, and performance considerations. By carefully selecting and implementing these strategies, developers can build scalable and robust applications that handle concurrency efficiently.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Concurrency issues can be tricky as they often arise when multiple requests hit your system at the same time, leading to unexpected behaviour and performance slowdowns. If you\u2019ve ever dealt with race conditions or inconsistent data updates, you know how frustrating it can be. In this article, we break down the complexities of concurrent programming<\/p>\n","protected":false},"author":129,"featured_media":28732,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_exactmetrics_skip_tracking":false,"_exactmetrics_sitenote_active":false,"_exactmetrics_sitenote_note":"","_exactmetrics_sitenote_category":0,"_themeisle_gutenberg_block_has_review":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_wpcom_ai_launchpad_first_post":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_post_was_ever_published":false},"categories":[1497],"tags":[],"class_list":["post-28728","post","type-post","status-publish","format-standard","has-post-thumbnail","category-engineering"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Optimising Concurrency in Spring Boot: Robust Solutions for Scalable Systems<\/title>\n<meta name=\"description\" content=\"Learn how to tackle concurrency issues in Spring Boot, prevent race conditions, and optimize performance with effective strategies for handling multiple requests seamlessly.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.cashfree.com\/blog\/optimising-concurrency-in-spring-boot\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Optimising Concurrency in Spring Boot: Robust Solutions for Scalable Systems\" \/>\n<meta property=\"og:description\" content=\"Learn how to tackle concurrency issues in Spring Boot, prevent race conditions, and optimize performance with effective strategies for handling multiple requests seamlessly.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.cashfree.com\/blog\/optimising-concurrency-in-spring-boot\/\" \/>\n<meta property=\"og:site_name\" content=\"Cashfree Payments Blog\" \/>\n<meta property=\"article:published_time\" content=\"2025-03-11T12:41:02+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-03-11T12:44:37+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/i0.wp.com\/blogrevamp.cashfree.com\/wp-content\/uploads\/2025\/03\/Aman-Suri-Blog_tnv3.png?fit=1094%2C613&ssl=1\" \/>\n\t<meta property=\"og:image:width\" content=\"1094\" \/>\n\t<meta property=\"og:image:height\" content=\"613\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Aman Suri\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Aman Suri\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"16 minutes\" \/>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Optimising Concurrency in Spring Boot: Robust Solutions for Scalable Systems","description":"Learn how to tackle concurrency issues in Spring Boot, prevent race conditions, and optimize performance with effective strategies for handling multiple requests seamlessly.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.cashfree.com\/blog\/optimising-concurrency-in-spring-boot\/","og_locale":"en_US","og_type":"article","og_title":"Optimising Concurrency in Spring Boot: Robust Solutions for Scalable Systems","og_description":"Learn how to tackle concurrency issues in Spring Boot, prevent race conditions, and optimize performance with effective strategies for handling multiple requests seamlessly.","og_url":"https:\/\/www.cashfree.com\/blog\/optimising-concurrency-in-spring-boot\/","og_site_name":"Cashfree Payments Blog","article_published_time":"2025-03-11T12:41:02+00:00","article_modified_time":"2025-03-11T12:44:37+00:00","og_image":[{"width":1094,"height":613,"url":"https:\/\/i0.wp.com\/blogrevamp.cashfree.com\/wp-content\/uploads\/2025\/03\/Aman-Suri-Blog_tnv3.png?fit=1094%2C613&ssl=1","type":"image\/png"}],"author":"Aman Suri","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Aman Suri","Est. reading time":"16 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.cashfree.com\/blog\/optimising-concurrency-in-spring-boot\/#article","isPartOf":{"@id":"https:\/\/blogrevamp.cashfree.com\/optimising-concurrency-in-spring-boot\/"},"author":{"name":"Aman Suri","@id":"https:\/\/blogrevamp.cashfree.com\/#\/schema\/person\/1578e77c389d3cef3cd305835a6ff57e"},"headline":"Optimising Concurrency in Spring Boot: Robust Solutions for Scalable Systems","datePublished":"2025-03-11T12:41:02+00:00","dateModified":"2025-03-11T12:44:37+00:00","mainEntityOfPage":{"@id":"https:\/\/blogrevamp.cashfree.com\/optimising-concurrency-in-spring-boot\/"},"wordCount":2003,"commentCount":0,"image":{"@id":"https:\/\/www.cashfree.com\/blog\/optimising-concurrency-in-spring-boot\/#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/blogrevamp.cashfree.com\/wp-content\/uploads\/2025\/03\/Aman-Suri-Blog_tnv3.png?fit=1094%2C613&ssl=1","articleSection":["Engineering"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.cashfree.com\/blog\/optimising-concurrency-in-spring-boot\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/blogrevamp.cashfree.com\/optimising-concurrency-in-spring-boot\/","url":"https:\/\/www.cashfree.com\/blog\/optimising-concurrency-in-spring-boot\/","name":"Optimising Concurrency in Spring Boot: Robust Solutions for Scalable Systems","isPartOf":{"@id":"https:\/\/blogrevamp.cashfree.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.cashfree.com\/blog\/optimising-concurrency-in-spring-boot\/#primaryimage"},"image":{"@id":"https:\/\/www.cashfree.com\/blog\/optimising-concurrency-in-spring-boot\/#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/blogrevamp.cashfree.com\/wp-content\/uploads\/2025\/03\/Aman-Suri-Blog_tnv3.png?fit=1094%2C613&ssl=1","datePublished":"2025-03-11T12:41:02+00:00","dateModified":"2025-03-11T12:44:37+00:00","author":{"@id":"https:\/\/blogrevamp.cashfree.com\/#\/schema\/person\/1578e77c389d3cef3cd305835a6ff57e"},"description":"Learn how to tackle concurrency issues in Spring Boot, prevent race conditions, and optimize performance with effective strategies for handling multiple requests seamlessly.","breadcrumb":{"@id":"https:\/\/www.cashfree.com\/blog\/optimising-concurrency-in-spring-boot\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.cashfree.com\/blog\/optimising-concurrency-in-spring-boot\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.cashfree.com\/blog\/optimising-concurrency-in-spring-boot\/#primaryimage","url":"https:\/\/i0.wp.com\/blogrevamp.cashfree.com\/wp-content\/uploads\/2025\/03\/Aman-Suri-Blog_tnv3.png?fit=1094%2C613&ssl=1","contentUrl":"https:\/\/i0.wp.com\/blogrevamp.cashfree.com\/wp-content\/uploads\/2025\/03\/Aman-Suri-Blog_tnv3.png?fit=1094%2C613&ssl=1","width":1094,"height":613},{"@type":"BreadcrumbList","@id":"https:\/\/www.cashfree.com\/blog\/optimising-concurrency-in-spring-boot\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/blogrevamp.cashfree.com\/"},{"@type":"ListItem","position":2,"name":"Engineering","item":"https:\/\/blogrevamp.cashfree.com\/category\/engineering\/"},{"@type":"ListItem","position":3,"name":"Optimising Concurrency in Spring Boot: Robust Solutions for Scalable Systems"}]},{"@type":"WebSite","@id":"https:\/\/blogrevamp.cashfree.com\/#website","url":"https:\/\/blogrevamp.cashfree.com\/","name":"Cashfree Payments Blog","description":"Cashfree Payments- Payment Gateway for India","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/blogrevamp.cashfree.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/blogrevamp.cashfree.com\/#\/schema\/person\/1578e77c389d3cef3cd305835a6ff57e","name":"Aman Suri","url":"https:\/\/blogrevamp.cashfree.com\/author\/aman-suri\/"}]}},"jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p9MjXo-7tm","jetpack_likes_enabled":false,"jetpack_featured_media_url":"https:\/\/i0.wp.com\/blogrevamp.cashfree.com\/wp-content\/uploads\/2025\/03\/Aman-Suri-Blog_tnv3.png?fit=1094%2C613&ssl=1","_links":{"self":[{"href":"https:\/\/blogrevamp.cashfree.com\/wp-json\/wp\/v2\/posts\/28728","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogrevamp.cashfree.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogrevamp.cashfree.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogrevamp.cashfree.com\/wp-json\/wp\/v2\/users\/129"}],"replies":[{"embeddable":true,"href":"https:\/\/blogrevamp.cashfree.com\/wp-json\/wp\/v2\/comments?post=28728"}],"version-history":[{"count":3,"href":"https:\/\/blogrevamp.cashfree.com\/wp-json\/wp\/v2\/posts\/28728\/revisions"}],"predecessor-version":[{"id":28738,"href":"https:\/\/blogrevamp.cashfree.com\/wp-json\/wp\/v2\/posts\/28728\/revisions\/28738"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blogrevamp.cashfree.com\/wp-json\/wp\/v2\/media\/28732"}],"wp:attachment":[{"href":"https:\/\/blogrevamp.cashfree.com\/wp-json\/wp\/v2\/media?parent=28728"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogrevamp.cashfree.com\/wp-json\/wp\/v2\/categories?post=28728"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogrevamp.cashfree.com\/wp-json\/wp\/v2\/tags?post=28728"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}