{"id":6414,"date":"2024-05-29T10:23:35","date_gmt":"2024-05-29T10:23:35","guid":{"rendered":"https:\/\/decentro.tech\/blog\/?p=6414"},"modified":"2024-06-12T12:45:56","modified_gmt":"2024-06-12T12:45:56","slug":"understanding-celery-simplifying-background-tasks-in-python","status":"publish","type":"post","link":"https:\/\/decentro.tech\/blog\/understanding-celery-simplifying-background-tasks-in-python\/","title":{"rendered":"Understanding Celery: Simplifying Background Tasks in Python"},"content":{"rendered":"<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_17 counter-hierarchy\">\n<div class=\"ez-toc-title-container\">\n<p class=\"ez-toc-title\">Table of Contents<\/p>\n<span class=\"ez-toc-title-toggle\"><\/span><\/div>\n<nav><ul class=\"ez-toc-list ez-toc-list-level-1\"><li class=\"ez-toc-page-1 ez-toc-heading-level-1\"><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/decentro.tech\/blog\/understanding-celery-simplifying-background-tasks-in-python\/#What_is_Celery\" title=\"What is Celery?\">What is Celery?<\/a><\/li><li class=\"ez-toc-page-1 ez-toc-heading-level-1\"><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/decentro.tech\/blog\/understanding-celery-simplifying-background-tasks-in-python\/#Use_Cases\" title=\"Use Cases\">Use Cases<\/a><ul class=\"ez-toc-list-level-2\"><li class=\"ez-toc-heading-level-2\"><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/decentro.tech\/blog\/understanding-celery-simplifying-background-tasks-in-python\/#Large_Dataset\" title=\"Large Dataset\">Large Dataset<\/a><\/li><li class=\"ez-toc-page-1 ez-toc-heading-level-2\"><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/decentro.tech\/blog\/understanding-celery-simplifying-background-tasks-in-python\/#Run_multiple_tasks\" title=\"Run multiple tasks\">Run multiple tasks<\/a><\/li><li class=\"ez-toc-page-1 ez-toc-heading-level-2\"><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/decentro.tech\/blog\/understanding-celery-simplifying-background-tasks-in-python\/#Background_Validation_of_Data\" title=\"Background Validation of Data\">Background Validation of Data<\/a><\/li><\/ul><\/li><li class=\"ez-toc-page-1 ez-toc-heading-level-1\"><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/decentro.tech\/blog\/understanding-celery-simplifying-background-tasks-in-python\/#Conclusion\" title=\"Conclusion\">Conclusion<\/a><\/li><\/ul><\/nav><\/div>\n\n<figure class=\"wp-block-image size-large featured-post-img\"><img loading=\"lazy\" width=\"1779\" height=\"1779\" src=\"https:\/\/decentro.tech\/blog\/wp-content\/uploads\/Celery_InternalBanner.jpg\" alt=\"\" class=\"wp-image-6419\"\/><\/figure>\n\n\n\n<p>API development is primarily done for real-time or near-real-time responses from systems, but what do you do when a large dataset takes time to prepare or when a task depends on sending an email?<\/p>\n\n\n\n<p>Enter our saviour &#8211; CELERY&nbsp;<\/p>\n\n\n\n<p>Although it&#8217;s a green vegetable that is good for health, in Python\u2019s case, it&#8217;s an even better tool for your system&#8217;s health.<\/p>\n\n\n\n<h1><span class=\"ez-toc-section\" id=\"What_is_Celery\"><\/span>What is Celery?<span class=\"ez-toc-section-end\"><\/span><\/h1>\n\n\n\n<p>Celery is a tool to maintain task queues based on distributed messaging systems.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" width=\"2232\" height=\"1332\" src=\"https:\/\/decentro.tech\/blog\/wp-content\/uploads\/Celery_PayrollManagementProcess.jpg\" alt=\"Architecture of Celery\" class=\"wp-image-6415\"\/><\/figure>\n\n\n\n<p>Task queue, as the name suggests, is a way of storing tasks which will be picked up by workers who will complete these tasks<\/p>\n\n\n\n<p>Distributed messaging systems manage messages so that the producer (python script\/API) and consumer (celery worker processes) can communicate with each other. Examples of such messaging systems are RabbitMQ, Redis, and AWS SQS.<\/p>\n\n\n\n<p>So, in a nutshell, Celery acts as a middleman between producer and consumer in managing the tasks.&nbsp;<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img src=\"https:\/\/lh7-us.googleusercontent.com\/sQg_tWCEu0CLnRoSu7a718ab_ptJpB_3Fi5gHmj1QYK5IOIje_5_ETdl3EYqx85UY3u48O8UZvwtAAycle_o8NVSTgw7n2rUasg1pvCDJ2JKhhliS7Dg7TNZ8j_pIWYBHwjuviPXtWW3UY-zCYWtqu0\" alt=\"Celery Workflow\"\/><figcaption>The workflow of Celery<\/figcaption><\/figure>\n\n\n\n<h1><span class=\"ez-toc-section\" id=\"Use_Cases\"><\/span>Use Cases<span class=\"ez-toc-section-end\"><\/span><\/h1>\n\n\n\n<p>Since it is slightly complicated to work with celery, why should I use it?<\/p>\n\n\n\n<p>I am going to break down this blog into 3 use cases:<\/p>\n\n\n\n<ol><li>Large dataset<\/li><li>Run multiple tasks<\/li><li>Background validation of data<\/li><\/ol>\n\n\n\n<p>Get your coffee ready; we are starting with a problem many of us have faced.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" width=\"220\" height=\"159\" src=\"https:\/\/decentro.tech\/blog\/wp-content\/uploads\/coffee-need-coffee.gif\" alt=\"\" class=\"wp-image-6416\"\/><\/figure><\/div>\n\n\n\n<h2><span class=\"ez-toc-section\" id=\"Large_Dataset\"><\/span>Large Dataset<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Our organisation relies heavily on data. Sometimes, extracting this data from our database using queries might take a few minutes. We do not want our users (internal or external) to wait for responses in real-time.&nbsp;<\/p>\n\n\n\n<p>Our users are happy to receive the extracted dataset through an asynchronous process, such as email or Slack.<\/p>\n\n\n\n<p>Celery to the rescue!!<\/p>\n\n\n\n<p>We can use Celery to create tasks that the workers can pick up asynchronously and process as background tasks.<\/p>\n\n\n\n<p>Steps to make this:<\/p>\n\n\n\n<ol><li>Create a restful API using any Python framework like Flask, Django or any other.<\/li><\/ol>\n\n\n\n<pre class=\"wp-block-code\"><code>from flask import Flask, jsonify, request\nfrom sqlalchemy import create_engine, Column, Integer, String\nfrom sqlalchemy.ext.declarative import declarative_base\nfrom sqlalchemy.orm import sessionmaker\n\napp = Flask(__name__)\napp.config&#91;'SQLALCHEMY_DATABASE_URI'] = 'sqlite:\/\/\/users.db'\napp.config&#91;'SQLALCHEMY_TRACK_MODIFICATIONS'] = False\n\nBase = declarative_base()\n\n# Define the User model\nclass User(Base):\n    __tablename__ = 'users'\n    id = Column(Integer, primary_key=True)\n    name = Column(String)\n\n# Create the database engine and session\nengine = create_engine(app.config&#91;'SQLALCHEMY_DATABASE_URI'])\nSession = sessionmaker(bind=engine)\n\n# Function to fetch users from the database\ndef fetch_users():\n    session = Session()\n    users = session.query(User).all()\n    session.close()\n    return &#91;{'id': user.id, 'name': user.name} for user in users]\n\n# Endpoint to get all users\n@app.route('\/users', methods=&#91;'GET'])\ndef get_users():\n    # Call the function fetch users from the database\n    task = fetch_users()\n    # Return a task ID to track the progress\n    return jsonify({\"task_id\": task.id}), 202\n\nif __name__ == '__main__':\n    # Create the database tables if they don't exist\n    Base.metadata.create_all(engine)\n    app.run(debug=True)\n<\/code><\/pre>\n\n\n\n<ol start=\"2\"><li>All the users\u2019 lists are fetched in the above example as a real-time operation. We will change this by adding celery to process users asynchronously. We will request to hit the fetch_users function, but it will not return the results. It will instead provide us with a task id which can later be used to obtain the results of that task using \/users\/&lt;task_id&gt; endpoint.<\/li><\/ol>\n\n\n\n<pre class=\"wp-block-code\"><code>from flask import Flask, jsonify, request\nfrom celery import Celery\nfrom sqlalchemy import create_engine, Column, Integer, String\nfrom sqlalchemy.ext.declarative import declarative_base\nfrom sqlalchemy.orm import sessionmaker\n\napp = Flask(__name__)\napp.config&#91;'CELERY_BROKER_URL'] = 'redis:\/\/localhost:6379\/0'\napp.config&#91;'CELERY_RESULT_BACKEND'] = 'redis:\/\/localhost:6379\/0'\napp.config&#91;'SQLALCHEMY_DATABASE_URI'] = 'sqlite:\/\/\/users.db'\napp.config&#91;'SQLALCHEMY_TRACK_MODIFICATIONS'] = False\n\ncelery = Celery(app.name, broker=app.config&#91;'CELERY_BROKER_URL'])\ncelery.conf.update(app.config)\n\nBase = declarative_base()\n\n# Define the User model\nclass User(Base):\n    __tablename__ = 'users'\n    id = Column(Integer, primary_key=True)\n    name = Column(String)\n\n# Create the database engine and session\nengine = create_engine(app.config&#91;'SQLALCHEMY_DATABASE_URI'])\nSession = sessionmaker(bind=engine)\n\n# Celery task to fetch users from the database\n@celery.task\ndef fetch_users():\n    session = Session()\n    users = session.query(User).all()\n    session.close()\n    return &#91;{'id': user.id, 'name': user.name} for user in users]\n\n# Endpoint to get all users\n@app.route('\/users', methods=&#91;'GET'])\ndef get_users():\n    # Call the Celery task to fetch users asynchronously\n    task = fetch_users.delay()\n    # Return a task ID to track the progress\n    return jsonify({\"task_id\": task.id}), 202\n\n# Endpoint to retrieve the result of the task\n@app.route('\/users\/&lt;task_id&gt;', methods=&#91;'GET'])\ndef get_users_task_result(task_id):\n    task = fetch_users.AsyncResult(task_id)\n    if task.state == 'SUCCESS':\n        return jsonify(task.result)\n    else:\n        return jsonify({\"message\": \"Task is still processing\"}), 202\n\nif __name__ == '__main__':\n    # Create the database tables if they don't exist\n    Base.metadata.create_all(engine)\n    app.run(debug=True)<\/code><\/pre>\n\n\n\n<h2><span class=\"ez-toc-section\" id=\"Run_multiple_tasks\"><\/span>Run multiple tasks<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Imagine you have an application that needs to perform multiple independent tasks, such as sending emails, generating reports, and updating user profiles, all triggered by a single API call. Celery shines in these scenarios by allowing you to run these tasks concurrently, thus speeding up the entire process.<\/p>\n\n\n\n<p>Here&#8217;s a basic example of how you can implement this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>from celery import Celery\n\napp = Celery('tasks', broker='redis:\/\/localhost:6379\/0', backend='redis:\/\/localhost:6379\/0')\n\n@app.task\ndef send_email(user_id):\n    # Logic to send email\n    return f\"Email sent to user {user_id}!\"\n\n@app.task\ndef generate_report(user_id):\n    # Logic to generate report\n    return f\"Report generated for user {user_id}!\"\n\n@app.task\ndef update_profile(user_id):\n    # Logic to update user profile\n    return f\"Profile updated for user {user_id}!\"\n\n# Example function to run multiple tasks\ndef handle_user_actions(user_id):\n    results = &#91;]\n    results.append(send_email.delay(user_id))\n    results.append(generate_report.delay(user_id))\n    results.append(update_profile.delay(user_id))\n    return results\n\n# In your Flask or Django views, you can call handle_user_actions to run these tasks asynchronously.<\/code><\/pre>\n\n\n\n<p>This is how we can define multiple tasks in Celery and trigger them asynchronously. The tasks will be executed concurrently by different worker processes, which can significantly reduce your API&#8217;s response time.<\/p>\n\n\n\n<h2><span class=\"ez-toc-section\" id=\"Background_Validation_of_Data\"><\/span>Background Validation of Data<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Now, let\u2019s discuss ensuring data integrity through background validation. For instance, after a user uploads a large dataset, you might need to validate it before it can be processed or analyzed. Running such validations in the background frees up your API to handle other requests and improves the overall user experience.<\/p>\n\n\n\n<p>Here\u2019s how you could set up such a process:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>from celery import Celery\n\napp = Celery('data_validation', broker='redis:\/\/localhost:6379\/0', backend='redis:\/\/localhost:6379\/0')\n\n@app.task\ndef validate_data(dataset_id):\n    # Placeholder for actual validation logic\n    valid = True  # Imagine some validation logic here\n    if valid:\n        return f\"Dataset {dataset_id} is valid.\"\n    else:\n        return f\"Dataset {dataset_id} contains errors.\"\n\n# Trigger this task from your API after a dataset is uploaded\ndef handle_data_upload(dataset_id):\n    # Asynchronously validate the data\n    result = validate_data.delay(dataset_id)\n    return result<\/code><\/pre>\n\n\n\n<p>In this example, the `validate_data` task checks the validity of the uploaded dataset. This task is triggered right after the dataset is uploaded and runs in the background without holding up the server. You can monitor the progress of the validation through Celery&#8217;s task ID and, once completed, take appropriate actions based on the validation results.<\/p>\n\n\n\n<h1><span class=\"ez-toc-section\" id=\"Conclusion\"><\/span><strong>Conclusion<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h1>\n\n\n\n<p><strong><em>We have been using Celery for more than two years here at Decentro, working on more than four projects and processing more than 4GB of data.<\/em><\/strong> I have been very happy with its stability and the ecosystem that has been built around It, which helps us introduce new features to our existing Celery deployments without many changes.<\/p>\n\n\n\n<p>I would highly recommend budding developers use this in their projects to improve their background and multiprocessing capabilities.<\/p>\n\n\n\n<p>P.S. We would use Celery in future projects to reduce task running times.<\/p>\n\n\n\n<p>With that, we have come to the end of another immersive experience of the production world.&nbsp;<\/p>\n\n\n\n<p>If you wish to read more such blogs, please check our website\u2019s [<a href=\"https:\/\/decentro.tech\/blog\/engineering-and-apis\/\" target=\"_blank\" rel=\"noreferrer noopener\">Blogs<\/a>] section. We have previously covered topics like&nbsp;<a href=\"https:\/\/decentro.tech\/blog\/jspdf\/\" target=\"_blank\" rel=\"noreferrer noopener\">JsPDF<\/a>,&nbsp;<a href=\"https:\/\/decentro.tech\/blog\/locust-load-testing\/\" target=\"_blank\" rel=\"noreferrer noopener\">Locust<\/a>, and much more.&nbsp;<\/p>\n\n\n\n<p><a class=\"decentro-homepage-signup\" href=\"https:\/\/decentro.tech\/signup?\" target=\"_blank\" rel=\"noreferrer noopener\">Let&#8217;s Connect<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Dive into how Decentro uses Celery to boost background tasks and efficiency in API development. Simplify your workflow and elevate your development projects with this guide.<\/p>\n","protected":false},"author":10,"featured_media":6621,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[23],"tags":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v15.7 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Understanding Celery: Simplifying Background Tasks in Python - Decentro<\/title>\n<meta name=\"description\" content=\"Dive into how Decentro uses Celery to boost background tasks and efficiency in API development. Simplify your workflow and elevate your development projects with this guide.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/decentro.tech\/blog\/understanding-celery-simplifying-background-tasks-in-python\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Understanding Celery: Simplifying Background Tasks in Python - Decentro\" \/>\n<meta property=\"og:description\" content=\"Dive into how Decentro uses Celery to boost background tasks and efficiency in API development. Simplify your workflow and elevate your development projects with this guide.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/decentro.tech\/blog\/understanding-celery-simplifying-background-tasks-in-python\/\" \/>\n<meta property=\"og:site_name\" content=\"Decentro\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/decentrotech\/\" \/>\n<meta property=\"article:published_time\" content=\"2024-05-29T10:23:35+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-06-12T12:45:56+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/decentro.tech\/blog\/wp-content\/uploads\/Celery_Main_Banner.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"3541\" \/>\n\t<meta property=\"og:image:height\" content=\"1780\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@DecentroTech\" \/>\n<meta name=\"twitter:site\" content=\"@DecentroTech\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\">\n\t<meta name=\"twitter:data1\" content=\"6 minutes\">\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebSite\",\"@id\":\"https:\/\/decentro.tech\/blog\/#website\",\"url\":\"https:\/\/decentro.tech\/blog\/\",\"name\":\"Decentro\",\"description\":\"API platform for banking integrations\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":\"https:\/\/decentro.tech\/blog\/?s={search_term_string}\",\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/decentro.tech\/blog\/understanding-celery-simplifying-background-tasks-in-python\/#primaryimage\",\"inLanguage\":\"en-US\",\"url\":\"https:\/\/decentro.tech\/blog\/wp-content\/uploads\/Celery_Main_Banner.jpg\",\"width\":3541,\"height\":1780},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/decentro.tech\/blog\/understanding-celery-simplifying-background-tasks-in-python\/#webpage\",\"url\":\"https:\/\/decentro.tech\/blog\/understanding-celery-simplifying-background-tasks-in-python\/\",\"name\":\"Understanding Celery: Simplifying Background Tasks in Python - Decentro\",\"isPartOf\":{\"@id\":\"https:\/\/decentro.tech\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/decentro.tech\/blog\/understanding-celery-simplifying-background-tasks-in-python\/#primaryimage\"},\"datePublished\":\"2024-05-29T10:23:35+00:00\",\"dateModified\":\"2024-06-12T12:45:56+00:00\",\"author\":{\"@id\":\"https:\/\/decentro.tech\/blog\/#\/schema\/person\/aa045712a482ec089e20e910f756dece\"},\"description\":\"Dive into how Decentro uses Celery to boost background tasks and efficiency in API development. Simplify your workflow and elevate your development projects with this guide.\",\"breadcrumb\":{\"@id\":\"https:\/\/decentro.tech\/blog\/understanding-celery-simplifying-background-tasks-in-python\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/decentro.tech\/blog\/understanding-celery-simplifying-background-tasks-in-python\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/decentro.tech\/blog\/understanding-celery-simplifying-background-tasks-in-python\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"item\":{\"@type\":\"WebPage\",\"@id\":\"https:\/\/decentro.tech\/blog\/\",\"url\":\"https:\/\/decentro.tech\/blog\/\",\"name\":\"Blog\"}},{\"@type\":\"ListItem\",\"position\":2,\"item\":{\"@type\":\"WebPage\",\"@id\":\"https:\/\/decentro.tech\/blog\/engineering-and-apis\/\",\"url\":\"https:\/\/decentro.tech\/blog\/engineering-and-apis\/\",\"name\":\"Engineering &amp; APIs\"}},{\"@type\":\"ListItem\",\"position\":3,\"item\":{\"@type\":\"WebPage\",\"@id\":\"https:\/\/decentro.tech\/blog\/understanding-celery-simplifying-background-tasks-in-python\/\",\"url\":\"https:\/\/decentro.tech\/blog\/understanding-celery-simplifying-background-tasks-in-python\/\",\"name\":\"Understanding Celery: Simplifying Background Tasks in Python\"}}]},{\"@type\":\"Person\",\"@id\":\"https:\/\/decentro.tech\/blog\/#\/schema\/person\/aa045712a482ec089e20e910f756dece\",\"name\":\"Shobhit Verma\",\"image\":{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/decentro.tech\/blog\/#personlogo\",\"inLanguage\":\"en-US\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/a4e80decb62b255327eee313ca610d60?s=96&d=mm&r=g\",\"caption\":\"Shobhit Verma\"},\"description\":\"CTO at Decentro. Making fintech great again!\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","_links":{"self":[{"href":"https:\/\/decentro.tech\/blog\/wp-json\/wp\/v2\/posts\/6414"}],"collection":[{"href":"https:\/\/decentro.tech\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/decentro.tech\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/decentro.tech\/blog\/wp-json\/wp\/v2\/users\/10"}],"replies":[{"embeddable":true,"href":"https:\/\/decentro.tech\/blog\/wp-json\/wp\/v2\/comments?post=6414"}],"version-history":[{"count":7,"href":"https:\/\/decentro.tech\/blog\/wp-json\/wp\/v2\/posts\/6414\/revisions"}],"predecessor-version":[{"id":6622,"href":"https:\/\/decentro.tech\/blog\/wp-json\/wp\/v2\/posts\/6414\/revisions\/6622"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/decentro.tech\/blog\/wp-json\/wp\/v2\/media\/6621"}],"wp:attachment":[{"href":"https:\/\/decentro.tech\/blog\/wp-json\/wp\/v2\/media?parent=6414"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/decentro.tech\/blog\/wp-json\/wp\/v2\/categories?post=6414"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/decentro.tech\/blog\/wp-json\/wp\/v2\/tags?post=6414"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}