{"id":46636,"date":"2021-03-12T00:00:00","date_gmt":"2021-03-12T08:00:00","guid":{"rendered":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/blog\/build-a-data-pipeline-for-weather-iot-with-fastapi-and-griddb\/"},"modified":"2025-11-13T12:55:14","modified_gmt":"2025-11-13T20:55:14","slug":"build-a-data-pipeline-for-weather-iot-with-fastapi-and-griddb","status":"publish","type":"post","link":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/blog\/build-a-data-pipeline-for-weather-iot-with-fastapi-and-griddb\/","title":{"rendered":"Build a Data Pipeline for Weather IoT with FastAPI and GridDB"},"content":{"rendered":"<p>In today&#8217;s blog post, we walk you through a practical guide on how you can use FastAPI and GridDB to build a robust data pipeline for your weather IoT project. By the end of this article, you&#8217;ll learn about the key components of a basic data pipeline architecture, as well as gain a good understanding on how you can further extend and apply the article&#8217;s example FastAPI implementation into your own use case. To keep the discussion easy to follow, this blog entry primarily focuses on building the data pipeline and integrating its various components. We won&#8217;t go into detail about setting up an IoT weather station, although we&#8217;ll also talk about steps to make the weather station a seamless part of the data pipeline itself. <a href=\"#source-code\"> FULL SOURCE CODE <\/a><\/p>\n<h2>Data Pipeline Overview<\/h2>\n<p>First, let&#8217;s get a big-picture view of the example data pipeline architecture we&#8217;ll be implementing. The data pipeline consists of three main components:<\/p>\n<ul>\n<li>Weather station: This includes the full HW and SW for monitoring temperature, air pressure, and humidity.<\/li>\n<li>GridDB server: This houses the time-series database where the weather data will be stored. <\/li>\n<li>FastAPI app: This provides the API endpoints, business logic, database connection layer, and other services for processing and returning data. In this setup, the FastAPI app handles incoming HTTP requests from the web. These include requests that activate the sensors as well as requests that fetch stored data from GridDB. The FastAPI app is also where other business logic and services such as parsing, validating, and processing data is executed. Later in this article, we&#8217;ll also talk about other possible data pipeline designs that may suit your use case better. For now, we&#8217;ll use this design to illustrate solutions on how we can nicely integrate FastAPI and GridDB together. <\/li>\n<\/ul>\n<h2>Requirements and Setup<\/h2>\n<p>Let&#8217;s now go over all the requirements and how they&#8217;re set up in this project.<\/p>\n<h3>Weather Station<\/h3>\n<p>For discussion purposes, our example assumes working with a hypothetical IoT home weather station that measures and monitors three physical quantities: temperature, pressure, and humidity. The sensors are hooked up to a Raspberry Pi, which also serves as the machine where our GridDB server and FastAPI app will be running.<\/p>\n<p>As mentioned, we won&#8217;t explain how to set up and configure the weather station here. Besides, you may even choose a different hardware setup for your weather station altogether. The important thing to note is that, in order for the weather station to properly integrate into the data pipeline, you need to make sure that all the libraries and packages for the sensors are installed in an environment where they&#8217;re visible to Python code in the FastAPI app. For example, if you&#8217;re using the<\/p>\n<p><a href=\"https:\/\/learn.adafruit.com\/dht\/overview\">DHT22 temperature and air pressure sensor<\/a>, the command import Adafruit_DHT shouldn&#8217;t raise an ImportError.<\/p>\n<h3>GridDB Server<\/h3>\n<p>GridDB is a good choice as the database for weather IoT systems. It&#8217;s optimized for IoT and supports a number of helpful time-series functionalities out of the box. To learn how to set up GridDB, checkout this guide on<\/p>\n<p><a href=\"https:\/\/griddb.net\/en\/blog\/griddb-on-arm-time-series-database-for-your-raspberry-pi\/\">installing GridDB on a Raspberry Pi<\/a>. Or to quickly get it up and running, build and run a suitable <a href=\"https:\/\/griddb.net\/en\/blog\/improve-your-devops-with-griddb-server-and-client-docker-containers\/\">GridDB Docker image<\/a> instead. In our example, we use a GridDB container to store the sensor data into appropriate columns: * timestamp or type TIMESTAMP * temperature of type DOUBLE * pressure of type DOUBLE * humidity of type DOUBLE To interact with GridDB, the FastAPI app uses the<\/p>\n<p><a href=\"https:\/\/github.com\/griddb\/python_client\">GridDB Python client<\/a> which can be <a href=\"https:\/\/griddb.net\/en\/blog\/python-client\/\">built and installed using this guide<\/a>.<\/p>\n<h3>FastAPI App<\/h3>\n<p>FastAPI is a <a href=\"https:\/\/fastapi.tiangolo.com\/\">high-performance framework <\/a>for quickly building web APIs. It&#8217;s easy to pick up and use, which means that creating apps with FastAPI requires shorter development times compared to other Python web frameworks. We install FastAPI with pip: <code>$ pip install fastapi<\/code> We also install an ASGI server for running the app in production: <code>$ pip install uvicorn[standard]<\/code><\/p>\n<p>To ensure there&#8217;s separation of concerns among different parts of the FastAPI app, here&#8217;s how we structure the project:<\/p>\n<p>. | .dockerignore | Dockerfile | init_griddb.py | requirements.txt | run.sh |<br \/>\n&#8212;app | main.py | <strong>init<\/strong>.py |<br \/>\n+&#8212;config | base.py | <strong>init<\/strong>.py |<br \/>\n+&#8212;db | connection.py | utils.py | <strong>init<\/strong>.py |<br \/>\n+&#8212;schema | response.py | <strong>init<\/strong>.py |<br \/>\n&#8212;services weatherstation.py <strong>init<\/strong>.py Here&#8217;s a summary of the key files and directories in the project:<\/p>\n<ul>\n<li>.\/init_griddb.py is a stand-alone Python script that creates the GridDB container<\/li>\n<li>.\/run.sh executes the GridDB initialization script and runs the uvicorn server.<\/li>\n<li>.\/app\/main.py is where the FastAPI app instance and endpoints are defined and set up. <\/li>\n<li>.\/app\/config\/ contains settings and configuration files. <\/li>\n<li>.\/app\/db\/ is the database access layer.<\/li>\n<li>.\/app\/schema\/ contains pydantic models that ensure the response body has the correct format. <\/li>\n<li>.\/app\/services\/ contains the app&#8217;s business logic (e.g., activating sensors and capturing data) Later, we&#8217;ll take a more in-depth look at the roles that these modules play in the data pipeline. <\/li>\n<\/ul>\n<h2>Data Pipeline<\/h2>\n<p>The FastAPI app ties together the different components of the data pipeline. Here&#8217;s how.<\/p>\n<h3>Configuration<\/h3>\n<p>Values for configuring the app are loaded or defined inside modules in the<\/p>\n<p><code>.\/app\/config\/<\/code> directory. In <code>.\/app\/config\/base.py<\/code>, the following settings are defined:<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-py\">import os\n\nGRIDDB_CONNECTION_PARAMS = {\n    \"notification_member\": os.environ.get(\n        \"GRIDDB_NOTIFICATION_MEMBER\",\n        \"griddb-server:10001\"\n    ),\n    \"cluster_name\": os.environ.get(\"GRIDDB_CLUSTER_NAME\", \"defaultCluster\"),\n    \"username\": os.environ.get(\"GRIDDB_USERNAME\", \"admin\"),\n    \"password\": os.environ.get(\"GRIDDB_PASSWORD\", \"admin\"),\n}\nGRIDDB_CONTAINER_NAME = os.environ.get(\n    \"GRIDDB_CONTAINER_NAME\",\n    \"weatherstation\"\n)<\/code><\/pre>\n<\/div>\n<p>It&#8217;s important to note that values for the settings are passed in as environment variables. Otherwise, default values are available. This helps prevent hard-coding sensitive information like database credentials and accidentally committing them to source control. Another thing to consider is that the connection parameters above imply that we&#8217;re acquiring a GridDB Store object via fixed-list method. Other methods are multicast method and provider method, each of which requires a different set of parameters.<\/p>\n<h3>Business Logic (Service Layer)<\/h3>\n<p>In our example, the app&#8217;s interaction with the weather station is defined in the file<\/p>\n<p><code>.\/app\/services\/weatherstation.py<\/code>. That file defines a function <code>get_sensor_data()<\/code> which activates all the sensors and captures their readings. This function returns a dictionary that contains the current timestamp, temperature, pressure, and humidity. Again, since we&#8217;re only using a hypothetical weather station, we won&#8217;t go into detail about this function&#8217;s implementation. The key thing to note is that the .\/app\/services\/ directory is where the code for your business logic should reside. You can add other functionalities here, such as helper or utility functions\/classes for processing the data further.<\/p>\n<h3>GridDB Access Layer<\/h3>\n<p>Next, we define a class that contains methods and attributes we need to manage GridDB connections and queries. We put this in the file .\/app\/db\/connection.py:<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-py\">import griddb_python as griddb\n\nfrom .utils import handle_exceptions\n\nclass GridDBConnection:\n    \"\"\"Convenience class for managing GridDB connection.\"\"\"\n\n    def __init__(self, connection_params: dict) -> None:\n        self.connection_params = connection_params\n        self.container_name = None\n        self.gridstore = None\n        self.container = None\n\n    @handle_exceptions\n    def init(self, container_name: str = None) -> None:\n        \"\"\"Sets gridstore and container instance.\"\"\"\n        factory = griddb.StoreFactory.get_instance()\n        self.gridstore = factory.get_store(**self.connection_params)\n        if container_name is not None:\n            self.container_name = container_name\n            self.container = self.gridstore.get_container(self.container_name)\n\n    @handle_exceptions\n    def create_container(self, container_info: griddb.ContainerInfo) -> None:\n        \"\"\"Creates container with given container info.\"\"\"\n        self.container_name = container_info.name\n        self.container = self.gridstore.put_container(container_info)\n\n    @handle_exceptions\n    def execute_and_fetch(self, query_stmt: str, as_dict: bool = False) -> list:\n        \"\"\"Executes query on `self.container` and returns results.\"\"\"\n        query = self.container.query(query_stmt)\n        row_set = query.fetch()\n\n        results = []\n        columns = row_set.get_column_names()\n\n        while row_set.has_next():\n            row = row_set.next()\n\n            if as_dict:\n                row = dict((k, v) for k, v in zip(columns, row))\n\n            results.append(row)\n\n        return results\n\n    def cleanup(self) -> None:\n        \"\"\"Closes container and store objects.\"\"\"\n        if self.container is not None:\n            self.container.close()\n\n        if self.gridstore is not None:\n            self.gridstore.close()<\/code><\/pre>\n<\/div>\n<p>We&#8217;ll see below how this class is used throughout the app. Note that the handle_exception decorator is defined in the file<\/p>\n<p><code>.\/app\/db\/utils.py<\/code>.<\/p>\n<h3>GridDB Container<\/h3>\n<p>Initialization To create the container for our weather station data, we include a stand-alone Python script that defines and initializes the container:<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-py\">#!\/usr\/bin\/python\nimport griddb_python as griddb\n\nfrom app.db.connection import GridDBConnection\nfrom app.config import GRIDDB_CONNECTION_PARAMS, GRIDDB_CONTAINER_NAME\n\ndef main() -> None:\n    try:\n        gdb = GridDBConnection(GRIDDB_CONNECTION_PARAMS)\n\n        print(\"Initializing GridDB connection\")\n        gdb.init()\n\n        print(f\"Creating container {GRIDDB_CONTAINER_NAME}\")\n        con_info = griddb.ContainerInfo(\n            name=GRIDDB_CONTAINER_NAME,\n            column_info_list=[\n                [\"timestamp\", griddb.Type.TIMESTAMP],\n                [\"temperature\", griddb.Type.DOUBLE],\n                [\"pressure\", griddb.Type.DOUBLE],\n                [\"humidity\", griddb.Type.DOUBLE],\n            ],\n            type=griddb.ContainerType.TIME_SERIES\n        )\n\n        gdb.create_container(con_info)\n\n        print('Done')\n    except Exception as e:\n        print(f\"Error initializing GridDB: {e}\")\n\nif __name__ == \"__main__\":\n    main()<\/code><\/pre>\n<\/div>\n<p>This script needs to be run before starting the uvicorn server. Alternatively, you can run the bash script<\/p>\n<p><code>.\/run.sh<\/code> instead.<\/p>\n<h3>GridDB Connection Setup<\/h3>\n<p>We want to establish a connection to the GridDB server once the app server starts, as well as to close the connection once the app server shuts down. In addition, we need the ability to access the instance of our GridDBConnection class throughout the app. To meet these requirements, we write part of the<\/p>\n<p><code>.\/app\/main.py<\/code> as follows:<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-py\">import logging\nfrom typing import Optional\n\nfrom fastapi import FastAPI, Response, status\n\nfrom .config import (\n    GRIDDB_CONNECTION_PARAMS,\n    GRIDDB_CONTAINER_NAME,\n)\nfrom .db import GridDBConnection\nfrom .schema import ResponseModel\nfrom .services.weatherstation import get_sensor_data\n\nlogger = logging.getLogger(\"api\")\n\napp = FastAPI()\n\n@app.on_event(\"startup\")\nasync def startup_event():\n    logger.info(\"Server startup\")\n\n    logger.info(\"Initializing GridDB connection\")\n    gdb = GridDBConnection(GRIDDB_CONNECTION_PARAMS)\n    gdb.init(GRIDDB_CONTAINER_NAME)\n\n    app.state.griddb = gdb\n    logger.info(\"Server Startup\")\n\n@app.on_event(\"shutdown\")\nasync def shutdown_event():\n    app.state.griddb.cleanup()\n    logger.info(\"Server Shutdown\")\n\n# ... Continued on next code block ...<\/code><\/pre>\n<\/div>\n<p>This ensures that connection to the GridDB server and selection of the weather station container both happen during app server startup. The created GridDBConnection is then assigned to the app.state.griddb attribute so that it can be used throughout the app.<\/p>\n<h3>API Endpoints The data pipeline receives requests from the web via two API endpoints. These endpoints are defined in the next part of the .\/app\/main.py file:<\/h3>\n<div class=\"clipboard\">\n<pre><code class=\"language-py\"># ... Continued from previous code block ...\n\n@app.post(\"\/record\", response_model=ResponseModel)\nasync def save_current_sensor_data(response: Response):\n    \"\"\"Gets data from sensors and stores it in GridDB.\"\"\"\n    sensor_data = get_sensor_data()\n    app.state.griddb.container.put(list(sensor_data.values()))\n\n    response.status_code = status.HTTP_201_CREATED\n    return {\n        \"status\": \"Successfully stored new reading\",\n        \"records\": 1,\n        \"data\": [sensor_data],\n    }\n\n@app.get(\"\/retrieve\", response_model=ResponseModel)\nasync def get_stored_readings(minutes: Optional[int] = 5):\n    \"\"\"Retrieves stored readings within given number of minutes ago.\"\"\"\n    stmt = f\"\"\"\n        select * \n        where timestamp > TIMESTAMPADD(MINUTE, NOW(), -{minutes})\n        order by timestamp desc\n    \"\"\"\n    data = app.state.griddb.execute_and_fetch(stmt, as_dict=True)\n\n    return {\n        \"status\": f\"Retrieved stored records within last {minutes} minutes\",\n        \"records\": len(data),\n        \"data\": data,\n    }<\/code><\/pre>\n<\/div>\n<p>Here, we can see the two API endpoints are:<\/p>\n<ul>\n<li>POST \/record <\/li>\n<li>GET \/retrieve <\/li>\n<\/ul>\n<p><code>\/record<\/code> activates the weather sensors and stores the current reading into GridDB. It accepts a POST request and returns a 201 CREATED response and a JSON body that includes the status message, record count, and the record stored. <code>\/retrieve<\/code> fetches the most recent records within a given number of minutes ago. It accepts a GET request and an optional query parameter minutes. It then returns a 200 OK response and a JSON body that includes the status message, record count, and an array of retrieved records.<\/p>\n<h3>Response Schema<\/h3>\n<p>A key advantage of working with the FastAPI framework is that it offers various features that ensure the app accepts and returns objects with the right data types and formatting without additional developer effort. One such feature is its use of pydantic models to parse and validate response content. We saw this above in the definitions of the two API endpoints where we pass in ResponseModel into the response_model argument of the function decorator. This makes sure that the response body follows the schema defined in the ResponseModel class in the file<\/p>\n<p><code>.\/app\/schema\/response.py<\/code>:<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-py\">from typing import List, Optional\n\nfrom pydantic import BaseModel\n\nclass ResponseModel(BaseModel):\n    status: str = \"ok\"\n    records: Optional[int] = 0\n    data: Optional[List[dict]] = []<\/code><\/pre>\n<\/div>\n<p>We&#8217;ll see usage examples of the API endpoints and response body in the next section.<\/p>\n<h2>Usage<\/h2>\n<p>To run the entire data pipeline, we first make sure that the weather station is properly hooked up and the GridDB server is already running. Once ready, we initialize the weather station container with:<\/p>\n<p><code>$ python init_griddb.py<\/code> After this, we then run the app server with: <code>$ uvicorn app.main:app --host 0.0.0.0 --port 80<\/code><\/p>\n<p>You can also just run the .\/run.sh bash file to execute both of the above commands in one go. This will make the API endpoints accessible via 127.0.01 (localhost) on port 80.<\/p>\n<p>Note that if you&#8217;re running this via docker container, the endpoints may not be accessible via localhost but through the docker containers or docker machine&#8217;s IP address instead.<\/p>\n<p>So, in the subsequent examples, please substitute the correct IP address and port for your settings. Let&#8217;s test the API endpoints using curl. First let&#8217;s activate the sensors and capture the current weather data: <code>$ curl -X POST http:\/\/IP_ADDRESS:PORT\/record<\/code><\/p>\n<p>This should return a response like this:<\/p>\n<p><code>{\"status\":\"Successfully stored new reading\",\"records\":1,\"data\":[{\"timestamp\":\"2021-02-17T10:18:06.509054\",\"temperature\":29.530784788460004,\"pressure\":1004.8003564430331,\"humidity\":64}]}<\/code><\/p>\n<p>To get the most recently-stored readings within the past 5 minutes (recall that if you don&#8217;t pass a value for the query parameter minutes, the default is 5):<\/p>\n<p><code>$ curl http:\/\/IP_ADDRESS:PORT\/retrieve<\/code> This produces the following response: <code>{\"status\":\"Retrieved stored records within last 5 minutes\",\"records\":3,\"data\":[{\"timestamp\":\"2021-02-17T10:23:54.940000\",\"temperature\":29.649967592036077,\"pressure\":1005.0168541036603,\"humidity\":53.0},{\"timestamp\":\"2021-02-17T10:23:52.531000\",\"temperature\":29.767032247389704,\"pressure\":991.8437893041985,\"humidity\":73.0},{\"timestamp\":\"2021-02-17T10:23:46.351000\",\"temperature\":31.720923387508172,\"pressure\":1011.998375306113,\"humidity\":95.0}]}<\/code> And for the past 10 minutes: <code>$ curl http:\/\/IP_ADDRESS:PORT\/retrieve?minutes=10<\/code> which gives us: <code>{\"status\":\"Retrieved stored records within last 10 minutes\",\"records\":7,\"data\":[{\"timestamp\":\"2021-02-17T10:23:54.940000\",\"temperature\":29.649967592036077,\"pressure\":1005.0168541036603,\"humidity\":53.0},{\"timestamp\":\"2021-02-17T10:23:52.531000\",\"temperature\":29.767032247389704,\"pressure\":991.8437893041985,\"humidity\":73.0},{\"timestamp\":\"2021-02-17T10:23:46.351000\",\"temperature\":31.720923387508172,\"pressure\":1011.998375306113,\"humidity\":95.0},{\"timestamp\":\"2021-02-17T10:18:34.288000\",\"temperature\":28.10441189566165,\"pressure\":1028.2311879177432,\"humidity\":67.0},{\"timestamp\":\"2021-02-17T10:18:30.304000\",\"temperature\":29.996273963137778,\"pressure\":1007.5716385639391,\"humidity\":52.0},{\"timestamp\":\"2021-02-17T10:18:22.655000\",\"temperature\":28.823514215164877,\"pressure\":989.7959636620639,\"humidity\":66.0},{\"timestamp\":\"2021-02-17T10:18:06.509000\",\"temperature\":29.530784788460004,\"pressure\":1004.8003564430331,\"humidity\":64.0}]}<\/code><\/p>\n<p>Now, we can do something like set a cron job or a Lambda Function to regularly invoke the <code>\/record<\/code> API. We can also integrate a dashboard or data visualization app to consume the <code>\/retrieve<\/code> API.<\/p>\n<h2>Further Considerations Here are some ideas to further extend the basic data pipeline we&#8217;ve implemented, as well as ways to take it into another direction:<\/h2>\n<ul>\n<li>Implement additional business logic such as data cleaning or data processing. With our project structure, it&#8217;s very easy to add new functionality and wire it up with an existing or additional endpoint. <\/li>\n<li>Use an MQTT message broker so that GridDB can directly listen for new sensor data. This is implemented in <a href=\"https:\/\/griddb.net\/en\/blog\/monitoring-temperature-sensor-data-with-an-arduino-based-plc-mqtt-node-red-griddb-and-grafana\/\">another GridDB tutorial here.<\/a> <\/li>\n<li>Handle both HTTP and MQTT protocols. There&#8217;s a FastAPI library called <a href=\"https:\/\/pypi.org\/project\/fastapi-mqtt\/\">fastapi-mqtt<\/a> that lets you do this. <\/li>\n<\/ul>\n<h2>Conclusion<\/h2>\n<p>With this article, we built a simple but extensible data pipeline implementation using FastAPI and GridDB for weather IoT. We learned that these tools can help us easily create and maintain data-intensive systems, especially with use cases that require seamless integration among many different IoT components.<\/p>\n<h2 id=\"source-code\">Source Code<\/h2>\n<p><a href=\"https:\/\/github.com\/griddbnet\/Blogs\/tree\/main\/Build%20a%20Data%20Pipeline%20for%20Weather%20IoT%20with%20FastAPI%20and%20GridDB\"> GitHub <\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In today&#8217;s blog post, we walk you through a practical guide on how you can use FastAPI and GridDB to build a robust data pipeline for your weather IoT project. By the end of this article, you&#8217;ll learn about the key components of a basic data pipeline architecture, as well as gain a good understanding [&hellip;]<\/p>\n","protected":false},"author":41,"featured_media":27338,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[121],"tags":[],"class_list":["post-46636","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.1.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Build a Data Pipeline for Weather IoT with FastAPI and GridDB | GridDB: Open Source Time Series Database for IoT<\/title>\n<meta name=\"description\" content=\"In today&#039;s blog post, we walk you through a practical guide on how you can use FastAPI and GridDB to build a robust data pipeline for your weather IoT\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/griddb.net\/en\/blog\/build-a-data-pipeline-for-weather-iot-with-fastapi-and-griddb\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Build a Data Pipeline for Weather IoT with FastAPI and GridDB | GridDB: Open Source Time Series Database for IoT\" \/>\n<meta property=\"og:description\" content=\"In today&#039;s blog post, we walk you through a practical guide on how you can use FastAPI and GridDB to build a robust data pipeline for your weather IoT\" \/>\n<meta property=\"og:url\" content=\"https:\/\/griddb.net\/en\/blog\/build-a-data-pipeline-for-weather-iot-with-fastapi-and-griddb\/\" \/>\n<meta property=\"og:site_name\" content=\"GridDB: Open Source Time Series Database for IoT\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/griddbcommunity\/\" \/>\n<meta property=\"article:published_time\" content=\"2021-03-12T08:00:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-11-13T20:55:14+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/wp-content\/uploads\/2021\/03\/44429-sunset_2560x1707.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"2560\" \/>\n\t<meta property=\"og:image:height\" content=\"1707\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"griddb-admin\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@GridDBCommunity\" \/>\n<meta name=\"twitter:site\" content=\"@GridDBCommunity\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"griddb-admin\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"13 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/griddb.net\/en\/blog\/build-a-data-pipeline-for-weather-iot-with-fastapi-and-griddb\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/griddb.net\/en\/blog\/build-a-data-pipeline-for-weather-iot-with-fastapi-and-griddb\/\"},\"author\":{\"name\":\"griddb-admin\",\"@id\":\"https:\/\/griddb.net\/en\/#\/schema\/person\/4fe914ca9576878e82f5e8dd3ba52233\"},\"headline\":\"Build a Data Pipeline for Weather IoT with FastAPI and GridDB\",\"datePublished\":\"2021-03-12T08:00:00+00:00\",\"dateModified\":\"2025-11-13T20:55:14+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/griddb.net\/en\/blog\/build-a-data-pipeline-for-weather-iot-with-fastapi-and-griddb\/\"},\"wordCount\":1859,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/griddb.net\/en\/#organization\"},\"image\":{\"@id\":\"https:\/\/griddb.net\/en\/blog\/build-a-data-pipeline-for-weather-iot-with-fastapi-and-griddb\/#primaryimage\"},\"thumbnailUrl\":\"\/wp-content\/uploads\/2021\/03\/44429-sunset_2560x1707.jpg\",\"articleSection\":[\"Blog\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/griddb.net\/en\/blog\/build-a-data-pipeline-for-weather-iot-with-fastapi-and-griddb\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/griddb.net\/en\/blog\/build-a-data-pipeline-for-weather-iot-with-fastapi-and-griddb\/\",\"url\":\"https:\/\/griddb.net\/en\/blog\/build-a-data-pipeline-for-weather-iot-with-fastapi-and-griddb\/\",\"name\":\"Build a Data Pipeline for Weather IoT with FastAPI and GridDB | GridDB: Open Source Time Series Database for IoT\",\"isPartOf\":{\"@id\":\"https:\/\/griddb.net\/en\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/griddb.net\/en\/blog\/build-a-data-pipeline-for-weather-iot-with-fastapi-and-griddb\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/griddb.net\/en\/blog\/build-a-data-pipeline-for-weather-iot-with-fastapi-and-griddb\/#primaryimage\"},\"thumbnailUrl\":\"\/wp-content\/uploads\/2021\/03\/44429-sunset_2560x1707.jpg\",\"datePublished\":\"2021-03-12T08:00:00+00:00\",\"dateModified\":\"2025-11-13T20:55:14+00:00\",\"description\":\"In today's blog post, we walk you through a practical guide on how you can use FastAPI and GridDB to build a robust data pipeline for your weather IoT\",\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/griddb.net\/en\/blog\/build-a-data-pipeline-for-weather-iot-with-fastapi-and-griddb\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/griddb.net\/en\/blog\/build-a-data-pipeline-for-weather-iot-with-fastapi-and-griddb\/#primaryimage\",\"url\":\"\/wp-content\/uploads\/2021\/03\/44429-sunset_2560x1707.jpg\",\"contentUrl\":\"\/wp-content\/uploads\/2021\/03\/44429-sunset_2560x1707.jpg\",\"width\":2560,\"height\":1707},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/griddb.net\/en\/#website\",\"url\":\"https:\/\/griddb.net\/en\/\",\"name\":\"GridDB: Open Source Time Series Database for IoT\",\"description\":\"GridDB is an open source time-series database with the performance of NoSQL and convenience of SQL\",\"publisher\":{\"@id\":\"https:\/\/griddb.net\/en\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/griddb.net\/en\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/griddb.net\/en\/#organization\",\"name\":\"Fixstars\",\"url\":\"https:\/\/griddb.net\/en\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/griddb.net\/en\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/griddb.net\/wp-content\/uploads\/2019\/04\/fixstars_logo_web_tagline.png\",\"contentUrl\":\"https:\/\/griddb.net\/wp-content\/uploads\/2019\/04\/fixstars_logo_web_tagline.png\",\"width\":200,\"height\":83,\"caption\":\"Fixstars\"},\"image\":{\"@id\":\"https:\/\/griddb.net\/en\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/griddbcommunity\/\",\"https:\/\/x.com\/GridDBCommunity\",\"https:\/\/www.linkedin.com\/company\/griddb-by-toshiba\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/griddb.net\/en\/#\/schema\/person\/4fe914ca9576878e82f5e8dd3ba52233\",\"name\":\"griddb-admin\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/griddb.net\/en\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/5bceca1cafc06886a7ba873e2f0a28011a1176c4dea59709f735b63ae30d0342?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/5bceca1cafc06886a7ba873e2f0a28011a1176c4dea59709f735b63ae30d0342?s=96&d=mm&r=g\",\"caption\":\"griddb-admin\"},\"url\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/author\/griddb-admin\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Build a Data Pipeline for Weather IoT with FastAPI and GridDB | GridDB: Open Source Time Series Database for IoT","description":"In today's blog post, we walk you through a practical guide on how you can use FastAPI and GridDB to build a robust data pipeline for your weather IoT","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:\/\/griddb.net\/en\/blog\/build-a-data-pipeline-for-weather-iot-with-fastapi-and-griddb\/","og_locale":"en_US","og_type":"article","og_title":"Build a Data Pipeline for Weather IoT with FastAPI and GridDB | GridDB: Open Source Time Series Database for IoT","og_description":"In today's blog post, we walk you through a practical guide on how you can use FastAPI and GridDB to build a robust data pipeline for your weather IoT","og_url":"https:\/\/griddb.net\/en\/blog\/build-a-data-pipeline-for-weather-iot-with-fastapi-and-griddb\/","og_site_name":"GridDB: Open Source Time Series Database for IoT","article_publisher":"https:\/\/www.facebook.com\/griddbcommunity\/","article_published_time":"2021-03-12T08:00:00+00:00","article_modified_time":"2025-11-13T20:55:14+00:00","og_image":[{"width":2560,"height":1707,"url":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/wp-content\/uploads\/2021\/03\/44429-sunset_2560x1707.jpg","type":"image\/jpeg"}],"author":"griddb-admin","twitter_card":"summary_large_image","twitter_creator":"@GridDBCommunity","twitter_site":"@GridDBCommunity","twitter_misc":{"Written by":"griddb-admin","Est. reading time":"13 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/griddb.net\/en\/blog\/build-a-data-pipeline-for-weather-iot-with-fastapi-and-griddb\/#article","isPartOf":{"@id":"https:\/\/griddb.net\/en\/blog\/build-a-data-pipeline-for-weather-iot-with-fastapi-and-griddb\/"},"author":{"name":"griddb-admin","@id":"https:\/\/griddb.net\/en\/#\/schema\/person\/4fe914ca9576878e82f5e8dd3ba52233"},"headline":"Build a Data Pipeline for Weather IoT with FastAPI and GridDB","datePublished":"2021-03-12T08:00:00+00:00","dateModified":"2025-11-13T20:55:14+00:00","mainEntityOfPage":{"@id":"https:\/\/griddb.net\/en\/blog\/build-a-data-pipeline-for-weather-iot-with-fastapi-and-griddb\/"},"wordCount":1859,"commentCount":0,"publisher":{"@id":"https:\/\/griddb.net\/en\/#organization"},"image":{"@id":"https:\/\/griddb.net\/en\/blog\/build-a-data-pipeline-for-weather-iot-with-fastapi-and-griddb\/#primaryimage"},"thumbnailUrl":"\/wp-content\/uploads\/2021\/03\/44429-sunset_2560x1707.jpg","articleSection":["Blog"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/griddb.net\/en\/blog\/build-a-data-pipeline-for-weather-iot-with-fastapi-and-griddb\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/griddb.net\/en\/blog\/build-a-data-pipeline-for-weather-iot-with-fastapi-and-griddb\/","url":"https:\/\/griddb.net\/en\/blog\/build-a-data-pipeline-for-weather-iot-with-fastapi-and-griddb\/","name":"Build a Data Pipeline for Weather IoT with FastAPI and GridDB | GridDB: Open Source Time Series Database for IoT","isPartOf":{"@id":"https:\/\/griddb.net\/en\/#website"},"primaryImageOfPage":{"@id":"https:\/\/griddb.net\/en\/blog\/build-a-data-pipeline-for-weather-iot-with-fastapi-and-griddb\/#primaryimage"},"image":{"@id":"https:\/\/griddb.net\/en\/blog\/build-a-data-pipeline-for-weather-iot-with-fastapi-and-griddb\/#primaryimage"},"thumbnailUrl":"\/wp-content\/uploads\/2021\/03\/44429-sunset_2560x1707.jpg","datePublished":"2021-03-12T08:00:00+00:00","dateModified":"2025-11-13T20:55:14+00:00","description":"In today's blog post, we walk you through a practical guide on how you can use FastAPI and GridDB to build a robust data pipeline for your weather IoT","inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/griddb.net\/en\/blog\/build-a-data-pipeline-for-weather-iot-with-fastapi-and-griddb\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/griddb.net\/en\/blog\/build-a-data-pipeline-for-weather-iot-with-fastapi-and-griddb\/#primaryimage","url":"\/wp-content\/uploads\/2021\/03\/44429-sunset_2560x1707.jpg","contentUrl":"\/wp-content\/uploads\/2021\/03\/44429-sunset_2560x1707.jpg","width":2560,"height":1707},{"@type":"WebSite","@id":"https:\/\/griddb.net\/en\/#website","url":"https:\/\/griddb.net\/en\/","name":"GridDB: Open Source Time Series Database for IoT","description":"GridDB is an open source time-series database with the performance of NoSQL and convenience of SQL","publisher":{"@id":"https:\/\/griddb.net\/en\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/griddb.net\/en\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/griddb.net\/en\/#organization","name":"Fixstars","url":"https:\/\/griddb.net\/en\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/griddb.net\/en\/#\/schema\/logo\/image\/","url":"https:\/\/griddb.net\/wp-content\/uploads\/2019\/04\/fixstars_logo_web_tagline.png","contentUrl":"https:\/\/griddb.net\/wp-content\/uploads\/2019\/04\/fixstars_logo_web_tagline.png","width":200,"height":83,"caption":"Fixstars"},"image":{"@id":"https:\/\/griddb.net\/en\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/griddbcommunity\/","https:\/\/x.com\/GridDBCommunity","https:\/\/www.linkedin.com\/company\/griddb-by-toshiba"]},{"@type":"Person","@id":"https:\/\/griddb.net\/en\/#\/schema\/person\/4fe914ca9576878e82f5e8dd3ba52233","name":"griddb-admin","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/griddb.net\/en\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/5bceca1cafc06886a7ba873e2f0a28011a1176c4dea59709f735b63ae30d0342?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/5bceca1cafc06886a7ba873e2f0a28011a1176c4dea59709f735b63ae30d0342?s=96&d=mm&r=g","caption":"griddb-admin"},"url":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/author\/griddb-admin\/"}]}},"_links":{"self":[{"href":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/wp-json\/wp\/v2\/posts\/46636","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/wp-json\/wp\/v2\/users\/41"}],"replies":[{"embeddable":true,"href":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/wp-json\/wp\/v2\/comments?post=46636"}],"version-history":[{"count":1,"href":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/wp-json\/wp\/v2\/posts\/46636\/revisions"}],"predecessor-version":[{"id":51312,"href":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/wp-json\/wp\/v2\/posts\/46636\/revisions\/51312"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/wp-json\/wp\/v2\/media\/27338"}],"wp:attachment":[{"href":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/wp-json\/wp\/v2\/media?parent=46636"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/wp-json\/wp\/v2\/categories?post=46636"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/wp-json\/wp\/v2\/tags?post=46636"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}