{"id":55642,"date":"2026-10-30T11:53:48","date_gmt":"2026-10-30T18:53:48","guid":{"rendered":"https:\/\/www.griddb.net\/?p=55642"},"modified":"2026-10-30T11:56:14","modified_gmt":"2026-10-30T18:56:14","slug":"bulk-loading-csv-data-into-griddb-cloud-with-embulk","status":"publish","type":"post","link":"https:\/\/www.griddb.net\/en\/blog\/bulk-loading-csv-data-into-griddb-cloud-with-embulk\/","title":{"rendered":"Bulk Loading CSV Data into GridDB Cloud with Embulk"},"content":{"rendered":"<p>\n<a href=\"https:\/\/www.embulk.org\/\">Embulk<\/a> is an open-source bulk data loader that moves records between databases, storage services, and file formats using plugins. GridDB has an official Embulk output plugin, <code>embulk-output-griddb<\/code>, which lets you load data from any Embulk input source (CSV files, other databases, cloud storage) straight into GridDB containers.\n<\/p>\n<p>\nThe plugin was written back in the Embulk 0.9 days, and getting it built and running in 2026 takes some work. The Maven repositories it depends on have shut down, it needs Java 8, and connecting to GridDB Cloud has some networking requirements that aren&#8217;t obvious at first. This post goes through the whole process, from a fresh download to 50,000 rows sitting in a GridDB Cloud container, including every problem we ran into along the way.\n<\/p>\n<p>\nHere&#8217;s the pipeline we&#8217;re building:\n<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-plaintext\">sample.csv --&gt; Embulk (csv parser) --&gt; embulk-output-griddb --&gt; GridDB Cloud<\/code><\/pre>\n<\/div>\n<h2 id=\"prerequisites\">Prerequisites<\/h2>\n<ul>\n<li><strong>Java 8.<\/strong> Embulk 0.9.x runs on JRuby and won&#8217;t start on Java 11 or newer. Don&#8217;t try to get around this by using a newer Embulk (0.11\/1.0). The plugin loading model changed completely in 0.10+, and this plugin relies on <code>embulk-core<\/code> APIs that don&#8217;t exist there anymore.<\/li>\n<li><strong>Embulk 0.9.17.<\/strong> Download the jar from the <a href=\"https:\/\/github.com\/embulk\/embulk\/releases\/tag\/v0.9.17\">Embulk GitHub releases page<\/a>.<\/li>\n<li><strong>The <code>embulk-output-griddb<\/code> source<\/strong>, which comes with three jars in its <code>lib\/<\/code> directory: <code>gridstore.jar<\/code>, <code>gridstore-jdbc.jar<\/code>, and <code>griddb-tools-common.jar<\/code>.<\/li>\n<li><strong>A GridDB Cloud instance<\/strong>, or a self-hosted cluster. We&#8217;ll get into the difference below.<\/li>\n<\/ul>\n<p>\nIf you use SDKMAN, installing Java 8 is one command:\n<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-sh\">$ sdk install java 8.0.402-tem<\/code><\/pre>\n<\/div>\n<p>\nSDKMAN also sets <code>JAVA_HOME<\/code>, which matters more than whatever <code>java<\/code> is on your PATH. Gradle reads <code>JAVA_HOME<\/code> directly, and the Gradle 4.1 wrapper this project uses can&#8217;t even parse the version string of a modern JDK. If you see this:\n<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-plaintext\">Could not determine java version from &#x27;21.0.4&#x27;.<\/code><\/pre>\n<\/div>\n<p>\nthen <code>JAVA_HOME<\/code> is pointing at the wrong JDK, even if <code>java -version<\/code> says 8.\n<\/p>\n<h2 id=\"gotcha-1-read-only-directories-from-the-zip\">Gotcha #1: read-only directories from the zip<\/h2>\n<p>\nThe plugin comes as a zip, and depending on how it was packaged, the extracted directories can end up with mode 555 (read-only, even for you). Gradle then fails with a confusing error about its cache:\n<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-plaintext\">Could not create service of type CrossBuildFileHashCache\r\n&gt; Failed to create parent directory &#x27;.gradle&#x27;<\/code><\/pre>\n<\/div>\n<p>\nThe fix:\n<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-sh\">$ chmod -R u+w embulk-output-griddb<\/code><\/pre>\n<\/div>\n<p>\nIf you still get the <code>CrossBuildFileHashCache<\/code> error after fixing permissions, there&#8217;s probably leftover state from an earlier failed build. Stop the Gradle daemon and clear the project cache:\n<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-sh\">$ .\/gradlew --stop\r\n$ rm -rf .gradle<\/code><\/pre>\n<\/div>\n<h2 id=\"gotcha-2-the-build-depends-on-dead-repositories\">Gotcha #2: the build depends on dead repositories<\/h2>\n<p>\nThis one takes the most work. The original <code>build.gradle<\/code> depends on three things that don&#8217;t exist anymore:\n<\/p>\n<ol>\n<li><strong>JCenter.<\/strong> JFrog shut down the <code>jcenter()<\/code> repository, and requests now redirect to Maven Central, which doesn&#8217;t have the same artifacts.<\/li>\n<li><strong>The Bintray Gradle plugin<\/strong>, which needs <code>http-builder:0.7.2<\/code>. That artifact was only ever on JCenter.<\/li>\n<li><strong>The jruby-gradle plugin&#8217;s rubygems proxies<\/strong> (<code>rubygems-proxy.torquebox.org<\/code> and <code>rubygems.lasagna.io<\/code>). One returns HTML error pages that Gradle tries to parse as POM files, and the other doesn&#8217;t resolve in DNS at all.<\/li>\n<\/ol>\n<p>\nOn top of that, <code>org.embulk:embulk-core:0.9.17<\/code> was also JCenter-only. Maven Central only has Embulk from 0.10.29 onward, so there&#8217;s no repository left that can resolve it.\n<\/p>\n<p>\nThe good news is you don&#8217;t need any of this to build the plugin jar. The Bintray and JRuby plugins are only used for publishing to Bintray (gone) and RubyGems. And all of the <code>embulk-core<\/code> classes are already inside the Embulk runtime jar you downloaded, so you can compile against that instead.\n<\/p>\n<p>\nPut <code>embulk-0.9.17.jar<\/code> in the project&#8217;s <code>lib\/<\/code> directory:\n<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-sh\">$ curl -L -o lib\/embulk-0.9.17.jar \\\r\n    https:\/\/github.com\/embulk\/embulk\/releases\/download\/v0.9.17\/embulk-0.9.17.jar<\/code><\/pre>\n<\/div>\n<p>\nThen replace <code>build.gradle<\/code> with this trimmed-down version:\n<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-groovy\">plugins {\r\n    id &quot;java&quot;\r\n    id &quot;checkstyle&quot;\r\n}\r\n\r\nrepositories {\r\n    mavenCentral()\r\n}\r\n\r\nversion = &quot;0.1.0&quot;\r\nsourceCompatibility = 1.8\r\ntargetCompatibility = 1.8\r\n\r\nconfigurations {\r\n    provided\r\n}\r\n\r\ndependencies {\r\n    compileOnly files(&quot;lib\/embulk-0.9.17.jar&quot;)\r\n    compile group: &#x27;com.sun.jersey&#x27;, name: &#x27;jersey-core&#x27;, version: &#x27;1.19.4&#x27;\r\n    compile files(&#x27;lib\/griddb-tools-common.jar&#x27;)\r\n    compile files(&quot;lib\/gridstore.jar&quot;)\r\n    compile files(&quot;lib\/gridstore-jdbc.jar&quot;)\r\n}\r\n\r\ntask classpath(type: Copy, dependsOn: [&quot;jar&quot;]) {\r\n    doFirst { file(&quot;classpath&quot;).deleteDir() }\r\n    from (configurations.runtime - configurations.provided + files(jar.archivePath))\r\n    into &quot;classpath&quot;\r\n}\r\nclean { delete &quot;classpath&quot; }\r\n\r\ncheckstyle {\r\n    configFile = file(&quot;${project.rootDir}\/config\/checkstyle\/checkstyle.xml&quot;)\r\n    toolVersion = &#x27;8.23&#x27;\r\n    ignoreFailures = true\r\n}\r\n\r\ntask &quot;package&quot;(dependsOn: [&quot;classpath&quot;]) {\r\n    doLast {\r\n        println &quot;&gt; Build succeeded.&quot;\r\n        println &quot;&gt; You can run embulk with &#x27;-L ${file(&quot;.&quot;).absolutePath}&#x27; argument.&quot;\r\n    }\r\n}<\/code><\/pre>\n<\/div>\n<p>\nWhat changed:\n<\/p>\n<ul>\n<li><code>jcenter()<\/code>, the Bintray plugin, and the JRuby plugin are removed, along with the <code>gem<\/code> and <code>gemPush<\/code> publishing tasks.<\/li>\n<li><code>embulk-core<\/code> is now a <code>compileOnly<\/code> dependency on the local jar. <code>compileOnly<\/code> keeps it off the runtime classpath, so the <code>classpath<\/code> task doesn&#8217;t copy the 40 MB Embulk runtime into the plugin output. That&#8217;s what the old <code>provided<\/code> configuration was doing manually.<\/li>\n<li><code>ignoreFailures = true<\/code> on checkstyle, so style warnings in the original source don&#8217;t fail the build.<\/li>\n<\/ul>\n<p>\nNow build it:\n<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-sh\">$ .\/gradlew package<\/code><\/pre>\n<\/div>\n<div class=\"clipboard\">\n<pre><code class=\"language-plaintext\">&gt; Task :compileJava\r\n&gt; Task :package\r\n&gt; Build succeeded.\r\n&gt; You can run embulk with &#x27;-L \/home\/user\/embulk-output-griddb&#x27; argument.\r\nBUILD SUCCESSFUL<\/code><\/pre>\n<\/div>\n<p>\nYou might see warnings that <code>gridstore.jar<\/code> is a &#8220;malformed jar.&#8221; The bundled jars have minimal manifests, and Gradle 4.x just warns about it. You can ignore them.\n<\/p>\n<p>\nThe build produces a <code>classpath\/<\/code> directory with the plugin jar and its dependencies. You point Embulk at it with the <code>-L<\/code> flag, and that&#8217;s it. Nothing gets installed system-wide.\n<\/p>\n<h2 id=\"understanding-the-connection-model\">Understanding the connection model<\/h2>\n<p>\nBefore configuring anything, it&#8217;s important to know that <strong>this plugin uses the GridDB native Java client (NoSQL interface), not the Web API.<\/strong> It connects over the binary protocol on the transaction port (10001 by default) and finds the cluster nodes in PROVIDER mode, which means it downloads a JSON file from a <code>provider_url<\/code> that lists the node addresses. I&#8217;m pointing this out because the other GridDB Cloud connectors use the Web API, and the networking requirements are completely different.\n<\/p>\n<h3 id=\"why-not-just-whitelist-your-ip\">Why not just whitelist your IP?<\/h3>\n<p>\nSince GridDB Cloud v3.2, native clients can connect over the public internet. You whitelist your IP in the &#8220;GridDB Access&#8221; tab, use the HTTPS provider URL, and add <code>connectionRoute=PUBLIC<\/code> to the connection. That&#8217;s covered in <a href=\"https:\/\/www.griddb.net\/en\/blog\/connecting-to-griddb-cloud-v3-2-from-your-local-dev-environment-no-vpn-no-vnet-peering\/\">Connecting to GridDB Cloud v3.2 from Your Local Dev Environment (No VPN, No VNet Peering)<\/a>, and it&#8217;s the first thing we tried.\n<\/p>\n<p>\n<strong>It doesn&#8217;t work with this plugin as shipped.<\/strong> HTTPS provider support comes from a separate library, <code>gridstore-advanced.jar<\/code>, and the <code>gridstore.jar<\/code> bundled with the plugin is an old build from before that existed. Pointing the plugin at the HTTPS provider URL fails right away:\n<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-plaintext\">[145005:JC_ILLEGAL_PROPERTY_ENTRY] HTTPS Provider not available\r\nbecause of lack of extra library<\/code><\/pre>\n<\/div>\n<h3 id=\"what-works-vnet-peering-and-the-http-provider\">What works: VNet peering and the HTTP provider<\/h3>\n<p>\nGridDB Cloud also serves the provider JSON from a plain HTTP URL, and the old client handles that fine. The catch is that the node addresses in that JSON are private IPs inside the GridDB Cloud VNet, and without the public route, your client has to reach them directly. So:\n<\/p>\n<ol>\n<li><strong>Run Embulk from inside a VNet peered to the GridDB Cloud tenant VNet.<\/strong> You can set up peering from the Cloud management console. Whitelisting your IP won&#8217;t give you a route to the private node addresses.<\/li>\n<li><strong>Use the HTTP provider URL<\/strong>, which is reachable from inside the peered network, instead of the HTTPS one.<\/li>\n<\/ol>\n<p>\nThat&#8217;s the setup we use for the rest of this post. If peering isn&#8217;t an option for you, you could try replacing the plugin&#8217;s <code>lib\/gridstore.jar<\/code> with a current client from the Cloud console&#8217;s library download, adding <code>gridstore-advanced.jar<\/code> next to it, referencing both in <code>build.gradle<\/code>, and using the HTTPS provider URL with <code>connectionRoute=PUBLIC<\/code>. We haven&#8217;t tested that with this plugin&#8217;s code, so your mileage may vary.\n<\/p>\n<p>\nOne more Azure note if you&#8217;re setting up peering: peered VNets can&#8217;t have overlapping address spaces, and Azure checks this across every VNet already peered to the GridDB Cloud side. If the Cloud VNet is already peered to another VNet using <code>10.0.0.0\/16<\/code>, yours can&#8217;t use <code>10.0.0.0\/16<\/code> either, even in a different subscription. Azure will reject it with <code>VnetAddressSpaceOverlapsWithAlreadyPeeredVnet<\/code>. Either pick an address space that doesn&#8217;t overlap, or run Embulk from a VM in a VNet that&#8217;s already peered.\n<\/p>\n<h2 id=\"configuring-the-pipeline\">Configuring the pipeline<\/h2>\n<p>\nHere&#8217;s a full <code>config.yml<\/code> that loads a four-column CSV with no header:\n<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-yaml\">in:\r\n  type: file\r\n  path_prefix: \/home\/user\/sample\r\n  parser:\r\n    charset: UTF-8\r\n    newline: LF\r\n    type: csv\r\n    delimiter: &#x27;,&#x27;\r\n    quote: &#x27;&quot;&#x27;\r\n    trim_if_not_quoted: false\r\n    allow_extra_columns: false\r\n    allow_optional_columns: false\r\n    columns:\r\n    - {name: id, type: long}\r\n    - {name: name, type: string}\r\n    - {name: quantity, type: long}\r\n    - {name: price, type: double}\r\n\r\nout:\r\n  type: griddb\r\n  mode_cluster: PROVIDER\r\n  provider_url: http:\/\/&lt;storage-account&gt;.blob.core.windows.net\/&lt;container&gt;\/&lt;cluster&gt;.json\r\n  cluster: &lt;your-cluster-name&gt;\r\n  database: &lt;your-database&gt;\r\n  container: con_25\r\n  user: &lt;your-user&gt;\r\n  password: &lt;your-password&gt;\r\n  mode_insert: replace\r\n  default_timezone: UTC\r\n  batch_size: 1000\r\n\r\nexec:\r\n  max_threads: 1\r\n  min_output_tasks: 1<\/code><\/pre>\n<\/div>\n<p>\nA few notes:\n<\/p>\n<ul>\n<li><strong><code>path_prefix<\/code> is a prefix, not a full path.<\/strong> <code>\/home\/user\/sample<\/code> matches <code>sample.csv<\/code>, <code>sample2.csv<\/code>, and so on. Embulk lists files in the parent directory, so the user running it needs read access there. The plugin&#8217;s bundled instructions assume you run everything as root out of <code>\/root<\/code>, but you don&#8217;t need to and shouldn&#8217;t.<\/li>\n<li><strong>Don&#8217;t add a gzip decoder unless your file is actually gzipped.<\/strong> A <code>decoders<\/code> block with gzip on a plain CSV fails with <code>Not in GZIP format<\/code>, which shows up wrapped in a misleading <code>DB schema is invalid<\/code> error.<\/li>\n<li><strong>The parser schema has to match the container.<\/strong> In <code>append<\/code> mode, the plugin checks your Embulk column types against the existing container and won&#8217;t run if they don&#8217;t match. In <code>replace<\/code> mode, it drops and recreates the container from your schema, which is easier for a first load.<\/li>\n<li><strong>Don&#8217;t skip the <code>exec<\/code> block.<\/strong> The next section explains why.<\/li>\n<\/ul>\n<h2 id=\"gotcha-3-parallel-output-tasks-race-on-container-creation\">Gotcha #3: parallel output tasks race on container creation<\/h2>\n<p>\nBy default, Embulk runs two output tasks per input task. If you run without the <code>exec<\/code> block and watch the logs, you&#8217;ll see both writers connect, and then a few milliseconds apart:\n<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-plaintext\">(embulk-output-executor-1): Create new container:con_25\r\n(embulk-output-executor-0): Create new container:con_25<\/code><\/pre>\n<\/div>\n<p>\nEach output task checks for the container and creates it on its own. In <code>replace<\/code> mode, that means two tasks can each drop and recreate the container without knowing about the other. In our 50,000-row test, the two tasks split the file (25,016 and 24,984 rows) and all 50,000 made it in, but that was luck. With a slower connection or a bigger file, one task&#8217;s replace could wipe out rows the other task already wrote.\n<\/p>\n<p>\nUntil the plugin fixes this, force a single output task:\n<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-yaml\">exec:\r\n  max_threads: 1\r\n  min_output_tasks: 1<\/code><\/pre>\n<\/div>\n<p>\nYou lose parallel writes, but the results are consistent from run to run.\n<\/p>\n<h2 id=\"running-it\">Running it<\/h2>\n<div class=\"clipboard\">\n<pre><code class=\"language-sh\">$ java -jar lib\/embulk-0.9.17.jar run config.yml -L .<\/code><\/pre>\n<\/div>\n<p>\n<code>-L .<\/code> points Embulk at the plugin project directory (the one with <code>classpath\/<\/code> in it).\n<\/p>\n<p>\nBefore a real run, it&#8217;s worth doing a preview. It only runs the input and parser, so it catches CSV and schema problems without touching GridDB:\n<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-sh\">$ java -jar lib\/embulk-0.9.17.jar preview config.yml -L .<\/code><\/pre>\n<\/div>\n<p>\nA successful run ends like this:\n<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-plaintext\">Finish import:\r\nDatabase: &lt;your-database&gt;\r\nContainer: con_25\r\nModel: replace\r\nTotal rows: 50000\r\nCommitted.<\/code><\/pre>\n<\/div>\n<p>\nAnd checking from the GridDB side:\n<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-plaintext\">$ griddb-cloud-cli sql query -s &quot;SELECT COUNT(*) from con_25&quot;\r\n[[{&quot;Name&quot;:&quot;&quot;,&quot;Type&quot;:&quot;LONG&quot;,&quot;Value&quot;:50000}]]<\/code><\/pre>\n<\/div>\n<p>\nAll 50,000 rows loaded from a CSV through the native client.\n<\/p>\n<h2 id=\"summary-of-the-traps\">Summary of the traps<\/h2>\n<table class=\"markdown-table\" style=\"border-collapse: collapse; width: 100%; margin: 1em 0;\">\n<thead>\n<tr>\n<th style=\"border: 1px solid #ddd; padding: 8px; background-color: #f2f2f2; color: #333; text-align: left;\">Symptom<\/th>\n<th style=\"border: 1px solid #ddd; padding: 8px; background-color: #f2f2f2; color: #333; text-align: left;\">Cause<\/th>\n<th style=\"border: 1px solid #ddd; padding: 8px; background-color: #f2f2f2; color: #333; text-align: left;\">Fix<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\"><code>Could not determine java version<\/code><\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">Gradle 4.1 reading a modern JDK from <code>JAVA_HOME<\/code><\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">Point <code>JAVA_HOME<\/code> at Java 8<\/td>\n<\/tr>\n<tr>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\"><code>Could not create service ... CrossBuildFileHashCache<\/code><\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">Read-only directories from the zip, or a stale daemon cache<\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\"><code>chmod -R u+w<\/code>, then <code>.\/gradlew --stop &amp;&amp; rm -rf .gradle<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\"><code>Could not find http-builder:0.7.2<\/code><\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">Bintray plugin depends on a JCenter-only artifact<\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">Remove the Bintray plugin<\/td>\n<\/tr>\n<tr>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\"><code>Could not parse POM ... torquebox.org<\/code><\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">JRuby plugin&#8217;s rubygems proxies are dead<\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">Remove the JRuby plugin<\/td>\n<\/tr>\n<tr>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\"><code>Could not find org.embulk:embulk-core:0.9.17<\/code><\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">Artifact was JCenter-only, never on Maven Central<\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\"><code>compileOnly files(\"lib\/embulk-0.9.17.jar\")<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\"><code>HTTPS Provider not available<\/code><\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">Bundled client is missing the HTTPS provider library<\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">Use the HTTP provider URL from inside a peered VNet<\/td>\n<\/tr>\n<tr>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\"><code>JC_BAD_CONNECTION ... connect timed out<\/code><\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">No route to the cluster&#8217;s private node addresses<\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">VNet peering, with the node ports open from your subnet<\/td>\n<\/tr>\n<tr>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\"><code>VnetAddressSpaceOverlapsWithAlreadyPeeredVnet<\/code><\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">Your VNet&#8217;s address space overlaps one already peered to the Cloud VNet<\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">Use a non-overlapping range, or run from an already-peered VNet<\/td>\n<\/tr>\n<tr>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\"><code>DB schema is invalid<\/code> (with a gzip error in the logs)<\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">gzip decoder on a plain-text file, or the parser and container schemas don&#8217;t match<\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">Remove the decoder; match the schemas or use <code>replace<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">Two <code>Create new container<\/code> log lines<\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">Output tasks race on container creation<\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\"><code>min_output_tasks: 1<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\"><code>TXN_DENY_REQUEST ... DENY(NoSQL)<\/code> and a low row count<\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">Cloud rejects native writes under concurrent load, and the plugin doesn&#8217;t retry or resume<\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">Lower concurrency, and always check with <code>COUNT(*)<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2 id=\"scaling-up-what-happens-under-concurrent-load\">Scaling up: what happens under concurrent load<\/h2>\n<p>\n50,000 rows is a smoke test, so we wanted to push it harder. We generated a 10-million-row CSV with the same four-column schema and ran <strong>three loader processes at the same time<\/strong>, each writing to its own container (<code>con_a<\/code>, <code>con_b<\/code>, <code>con_c<\/code>). Each process had <code>min_output_tasks: 1<\/code> set so the container-creation race from Gotcha #3 wasn&#8217;t a factor. The goal was to see how the native client and GridDB Cloud handle concurrent load.\n<\/p>\n<p>\nAll three runs died within about 100 milliseconds of each other. Here are the row counts:\n<\/p>\n<table class=\"markdown-table\" style=\"border-collapse: collapse; width: 100%; margin: 1em 0;\">\n<thead>\n<tr>\n<th style=\"border: 1px solid #ddd; padding: 8px; background-color: #f2f2f2; color: #333; text-align: left;\">Container<\/th>\n<th style=\"border: 1px solid #ddd; padding: 8px; background-color: #f2f2f2; color: #333; text-align: left;\">Rows loaded<\/th>\n<th style=\"border: 1px solid #ddd; padding: 8px; background-color: #f2f2f2; color: #333; text-align: left;\">Expected<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">con_a<\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">922,484<\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">10,000,000<\/td>\n<\/tr>\n<tr>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">con_b<\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">922,484<\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">10,000,000<\/td>\n<\/tr>\n<tr>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">con_c<\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">918,268<\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">10,000,000<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>\nEach process dropped roughly 9 million rows. The logs show why:\n<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-plaintext\">[10104:TXN_DENY_REQUEST] Request constraints occured,\r\nrule is DENY(NoSQL) (address=172.26.30.69:10001, partitionId=170)<\/code><\/pre>\n<\/div>\n<p>\nGridDB Cloud rejected the writes on the server side. <code>DENY(NoSQL)<\/code> is a Cloud constraint that refuses native (NoSQL interface) requests under concurrent load. All three processes hit it at the same moment, which is why they failed so close together and ended up with nearly identical row counts.\n<\/p>\n<p>\nThe bigger problem is what the plugin does after that: nothing. <strong>There&#8217;s no retry and no resume.<\/strong> Any batches in flight are lost, and since the load runs in <code>replace<\/code> mode, you&#8217;re left with a container that only holds what was committed before the denial. The process exits, and unless you run a <code>COUNT(*)<\/code> afterward, it looks like the load worked. In our case it quietly lost 91% of the data.\n<\/p>\n<p>\nIf you&#8217;re running this plugin against GridDB Cloud in production, keep this in mind: <strong>without a row-count check, a partial load looks the same as a successful one.<\/strong>\n<\/p>\n<p>\nTwo smaller issues showed up in the same logs:\n<\/p>\n<ul>\n<li><code>PooledBufferAllocator$BufferDoubleReleasedException: Detected double release() call of a buffer<\/code>: the plugin&#8217;s error handling releases a buffer twice when a write fails. It doesn&#8217;t matter much since the run is already dying, but it&#8217;s still a bug in the failure path.<\/li>\n<li><code>Cannot create container<\/code> \/ <code>DB schema is invalid<\/code>: the three processes stepping on each other&#8217;s container operations after the denial. This is fallout from the main failure, not a separate bug.<\/li>\n<\/ul>\n<h3 id=\"takeaways\">Takeaways<\/h3>\n<ul>\n<li><strong>Concurrent native-client writes to GridDB Cloud can trigger a <code>TXN_DENY_REQUEST<\/code> constraint.<\/strong> It&#8217;s worth checking your plan to see whether that&#8217;s a connection limit, a request-rate limit, or something tier-specific.<\/li>\n<li><strong>The plugin doesn&#8217;t recover from a denial mid-load.<\/strong> No retry, no resume, and no clear signal that the load was incomplete. Always verify with a row count.<\/li>\n<li><strong><code>replace<\/code> mode makes this worse<\/strong>, because a failed load leaves you with a truncated container instead of an untouched one.<\/li>\n<\/ul>\n<p>\nNext we&#8217;ll narrow down the cause: one process loading all 10M rows (to rule out a hard volume cap), then two concurrent processes (to see if the denial still fires at lower concurrency). That should show where the concurrency limit actually sits, and we&#8217;ll cover it in a follow-up post.\n<\/p>\n<h2 id=\"embulk-vs-fluentd-choosing-the-right-tool\">Embulk vs Fluentd: choosing the right tool<\/h2>\n<p>\nNone of this means Embulk is a bad tool. Embulk and Fluentd are built for different jobs, and what broke here was using a batch loader for something that behaves more like a streaming workload: a lot of data pushed at a rate-limited endpoint that pushes back.\n<\/p>\n<p>\n<strong>Fluentd is built for high-volume, continuous streaming ingestion.<\/strong> Data keeps arriving and has to be delivered reliably as it comes in. Fluentd keeps a buffer on the client side (in memory or on disk), so when GridDB pushes back, it holds onto the data and retries until GridDB accepts it. That&#8217;s why Fluentd handles the same rate and concurrency limits that broke the Embulk run.\n<\/p>\n<p>\n<strong>Embulk is built for bulk, batch transfers.<\/strong> Think one-time migrations or scheduled loads of large, fixed datasets between structured datastores. That&#8217;s where it has the edge:\n<\/p>\n<ul>\n<li><strong>Batch migration is what it&#8217;s for.<\/strong> Moving a known dataset from A to B, like a database dump, a folder of CSV or Parquet files, or a table migration. If you need to load 50 million existing rows once, Embulk fits that job and Fluentd doesn&#8217;t.<\/li>\n<li><strong>Lots of datastore connectors.<\/strong> Embulk has plugins for databases, files, and cloud storage (MySQL, PostgreSQL, S3, BigQuery, CSV, JSON, Parquet, and more). It&#8217;s designed to move data between systems, while Fluentd&#8217;s plugins lean toward log and event sources and observability backends.<\/li>\n<li><strong>Explicit schema and type mapping.<\/strong> Embulk parses input with defined column types and per-column config (type conversion, timestamp formatting) and maps the source schema to the destination. Fluentd treats records as loosely typed events.<\/li>\n<li><strong>You can check that it finished.<\/strong> A batch job has a start and an end, so you can confirm all N rows made it with a row count. Fluentd runs continuously, so &#8220;did everything arrive&#8221; doesn&#8217;t really apply.<\/li>\n<li><strong>Repeatable transforms.<\/strong> The same input and config give you the same output, which is what you want for ETL and scheduled loads.<\/li>\n<\/ul>\n<p>\nIn short: <strong>use Fluentd for continuous streaming, and Embulk for bulk or batch migration between structured systems.<\/strong>\n<\/p>\n<p>\nOne caveat for this post specifically: the plugin&#8217;s lack of retry and resume makes Embulk a weaker fit for GridDB Cloud than it would otherwise be. It&#8217;s still the better tool for batch migration in general, but loading large volumes into GridDB Cloud with the current plugin means adding your own guardrails: run a single process, tune the batch size, and ideally wrap it in some retry logic. Against a self-hosted GridDB cluster, where those Cloud-side limits don&#8217;t apply, Embulk&#8217;s strengths come through a lot more cleanly.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Embulk is an open-source bulk data loader that moves records between databases, storage services, and file formats using plugins. GridDB has an official Embulk output plugin, embulk-output-griddb, which lets you load data from any Embulk input source (CSV files, other databases, cloud storage) straight into GridDB containers. The plugin was written back in the Embulk [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":55650,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[121],"tags":[],"class_list":["post-55642","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 v28.8 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Bulk Loading CSV Data into GridDB Cloud with Embulk | GridDB: Open Source Time Series Database for IoT<\/title>\n<meta name=\"description\" content=\"Embulk is an open-source bulk data loader that moves records between databases, storage services, and file formats using plugins. GridDB has an official\" \/>\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.griddb.net\/en\/blog\/bulk-loading-csv-data-into-griddb-cloud-with-embulk\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Bulk Loading CSV Data into GridDB Cloud with Embulk | GridDB: Open Source Time Series Database for IoT\" \/>\n<meta property=\"og:description\" content=\"Embulk is an open-source bulk data loader that moves records between databases, storage services, and file formats using plugins. GridDB has an official\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.griddb.net\/en\/blog\/bulk-loading-csv-data-into-griddb-cloud-with-embulk\/\" \/>\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=\"2026-10-30T18:53:48+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-10-30T18:56:14+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.griddb.net\/wp-content\/uploads\/2026\/10\/embulk-griddb-featured1.png\" \/>\n\t<meta property=\"og:image:width\" content=\"2400\" \/>\n\t<meta property=\"og:image:height\" content=\"1260\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Israel\" \/>\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=\"Israel\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"11 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.griddb.net\\\/en\\\/blog\\\/bulk-loading-csv-data-into-griddb-cloud-with-embulk\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.griddb.net\\\/en\\\/blog\\\/bulk-loading-csv-data-into-griddb-cloud-with-embulk\\\/\"},\"author\":{\"name\":\"Israel\",\"@id\":\"https:\\\/\\\/www.griddb.net\\\/#\\\/schema\\\/person\\\/eeee7aa92afb46bc7690a605e4656f9e\"},\"headline\":\"Bulk Loading CSV Data into GridDB Cloud with Embulk\",\"datePublished\":\"2026-10-30T18:53:48+00:00\",\"dateModified\":\"2026-10-30T18:56:14+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.griddb.net\\\/en\\\/blog\\\/bulk-loading-csv-data-into-griddb-cloud-with-embulk\\\/\"},\"wordCount\":2520,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.griddb.net\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.griddb.net\\\/en\\\/blog\\\/bulk-loading-csv-data-into-griddb-cloud-with-embulk\\\/#primaryimage\"},\"thumbnailUrl\":\"\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/embulk-griddb-featured1.png\",\"articleSection\":[\"Blog\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.griddb.net\\\/en\\\/blog\\\/bulk-loading-csv-data-into-griddb-cloud-with-embulk\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.griddb.net\\\/en\\\/blog\\\/bulk-loading-csv-data-into-griddb-cloud-with-embulk\\\/\",\"url\":\"https:\\\/\\\/www.griddb.net\\\/en\\\/blog\\\/bulk-loading-csv-data-into-griddb-cloud-with-embulk\\\/\",\"name\":\"Bulk Loading CSV Data into GridDB Cloud with Embulk | GridDB: Open Source Time Series Database for IoT\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.griddb.net\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.griddb.net\\\/en\\\/blog\\\/bulk-loading-csv-data-into-griddb-cloud-with-embulk\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.griddb.net\\\/en\\\/blog\\\/bulk-loading-csv-data-into-griddb-cloud-with-embulk\\\/#primaryimage\"},\"thumbnailUrl\":\"\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/embulk-griddb-featured1.png\",\"datePublished\":\"2026-10-30T18:53:48+00:00\",\"dateModified\":\"2026-10-30T18:56:14+00:00\",\"description\":\"Embulk is an open-source bulk data loader that moves records between databases, storage services, and file formats using plugins. GridDB has an official\",\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.griddb.net\\\/en\\\/blog\\\/bulk-loading-csv-data-into-griddb-cloud-with-embulk\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.griddb.net\\\/en\\\/blog\\\/bulk-loading-csv-data-into-griddb-cloud-with-embulk\\\/#primaryimage\",\"url\":\"\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/embulk-griddb-featured1.png\",\"contentUrl\":\"\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/embulk-griddb-featured1.png\",\"width\":2400,\"height\":1260},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.griddb.net\\\/#website\",\"url\":\"https:\\\/\\\/www.griddb.net\\\/\",\"name\":\"GridDB: Open Source Time Series Database for IoT\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.griddb.net\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.griddb.net\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.griddb.net\\\/#organization\",\"name\":\"Fixstars\",\"url\":\"https:\\\/\\\/www.griddb.net\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.griddb.net\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.griddb.net\\\/wp-content\\\/uploads\\\/2019\\\/04\\\/fixstars_logo_web_tagline.png\",\"contentUrl\":\"https:\\\/\\\/www.griddb.net\\\/wp-content\\\/uploads\\\/2019\\\/04\\\/fixstars_logo_web_tagline.png\",\"width\":200,\"height\":83,\"caption\":\"Fixstars\"},\"image\":{\"@id\":\"https:\\\/\\\/www.griddb.net\\\/#\\\/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:\\\/\\\/www.griddb.net\\\/#\\\/schema\\\/person\\\/eeee7aa92afb46bc7690a605e4656f9e\",\"name\":\"Israel\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/4df8cfc155402a2928d11f80b0220037b8bd26c4f1b19c4598d826e0306e6307?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/4df8cfc155402a2928d11f80b0220037b8bd26c4f1b19c4598d826e0306e6307?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/4df8cfc155402a2928d11f80b0220037b8bd26c4f1b19c4598d826e0306e6307?s=96&d=mm&r=g\",\"caption\":\"Israel\"},\"url\":\"https:\\\/\\\/www.griddb.net\\\/en\\\/author\\\/israel\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Bulk Loading CSV Data into GridDB Cloud with Embulk | GridDB: Open Source Time Series Database for IoT","description":"Embulk is an open-source bulk data loader that moves records between databases, storage services, and file formats using plugins. GridDB has an official","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.griddb.net\/en\/blog\/bulk-loading-csv-data-into-griddb-cloud-with-embulk\/","og_locale":"en_US","og_type":"article","og_title":"Bulk Loading CSV Data into GridDB Cloud with Embulk | GridDB: Open Source Time Series Database for IoT","og_description":"Embulk is an open-source bulk data loader that moves records between databases, storage services, and file formats using plugins. GridDB has an official","og_url":"https:\/\/www.griddb.net\/en\/blog\/bulk-loading-csv-data-into-griddb-cloud-with-embulk\/","og_site_name":"GridDB: Open Source Time Series Database for IoT","article_publisher":"https:\/\/www.facebook.com\/griddbcommunity\/","article_published_time":"2026-10-30T18:53:48+00:00","article_modified_time":"2026-10-30T18:56:14+00:00","og_image":[{"width":2400,"height":1260,"url":"https:\/\/www.griddb.net\/wp-content\/uploads\/2026\/10\/embulk-griddb-featured1.png","type":"image\/png"}],"author":"Israel","twitter_card":"summary_large_image","twitter_creator":"@GridDBCommunity","twitter_site":"@GridDBCommunity","twitter_misc":{"Written by":"Israel","Est. reading time":"11 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.griddb.net\/en\/blog\/bulk-loading-csv-data-into-griddb-cloud-with-embulk\/#article","isPartOf":{"@id":"https:\/\/www.griddb.net\/en\/blog\/bulk-loading-csv-data-into-griddb-cloud-with-embulk\/"},"author":{"name":"Israel","@id":"https:\/\/www.griddb.net\/#\/schema\/person\/eeee7aa92afb46bc7690a605e4656f9e"},"headline":"Bulk Loading CSV Data into GridDB Cloud with Embulk","datePublished":"2026-10-30T18:53:48+00:00","dateModified":"2026-10-30T18:56:14+00:00","mainEntityOfPage":{"@id":"https:\/\/www.griddb.net\/en\/blog\/bulk-loading-csv-data-into-griddb-cloud-with-embulk\/"},"wordCount":2520,"commentCount":0,"publisher":{"@id":"https:\/\/www.griddb.net\/#organization"},"image":{"@id":"https:\/\/www.griddb.net\/en\/blog\/bulk-loading-csv-data-into-griddb-cloud-with-embulk\/#primaryimage"},"thumbnailUrl":"\/wp-content\/uploads\/2026\/10\/embulk-griddb-featured1.png","articleSection":["Blog"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.griddb.net\/en\/blog\/bulk-loading-csv-data-into-griddb-cloud-with-embulk\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.griddb.net\/en\/blog\/bulk-loading-csv-data-into-griddb-cloud-with-embulk\/","url":"https:\/\/www.griddb.net\/en\/blog\/bulk-loading-csv-data-into-griddb-cloud-with-embulk\/","name":"Bulk Loading CSV Data into GridDB Cloud with Embulk | GridDB: Open Source Time Series Database for IoT","isPartOf":{"@id":"https:\/\/www.griddb.net\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.griddb.net\/en\/blog\/bulk-loading-csv-data-into-griddb-cloud-with-embulk\/#primaryimage"},"image":{"@id":"https:\/\/www.griddb.net\/en\/blog\/bulk-loading-csv-data-into-griddb-cloud-with-embulk\/#primaryimage"},"thumbnailUrl":"\/wp-content\/uploads\/2026\/10\/embulk-griddb-featured1.png","datePublished":"2026-10-30T18:53:48+00:00","dateModified":"2026-10-30T18:56:14+00:00","description":"Embulk is an open-source bulk data loader that moves records between databases, storage services, and file formats using plugins. GridDB has an official","inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.griddb.net\/en\/blog\/bulk-loading-csv-data-into-griddb-cloud-with-embulk\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.griddb.net\/en\/blog\/bulk-loading-csv-data-into-griddb-cloud-with-embulk\/#primaryimage","url":"\/wp-content\/uploads\/2026\/10\/embulk-griddb-featured1.png","contentUrl":"\/wp-content\/uploads\/2026\/10\/embulk-griddb-featured1.png","width":2400,"height":1260},{"@type":"WebSite","@id":"https:\/\/www.griddb.net\/#website","url":"https:\/\/www.griddb.net\/","name":"GridDB: Open Source Time Series Database for IoT","description":"","publisher":{"@id":"https:\/\/www.griddb.net\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.griddb.net\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.griddb.net\/#organization","name":"Fixstars","url":"https:\/\/www.griddb.net\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.griddb.net\/#\/schema\/logo\/image\/","url":"https:\/\/www.griddb.net\/wp-content\/uploads\/2019\/04\/fixstars_logo_web_tagline.png","contentUrl":"https:\/\/www.griddb.net\/wp-content\/uploads\/2019\/04\/fixstars_logo_web_tagline.png","width":200,"height":83,"caption":"Fixstars"},"image":{"@id":"https:\/\/www.griddb.net\/#\/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:\/\/www.griddb.net\/#\/schema\/person\/eeee7aa92afb46bc7690a605e4656f9e","name":"Israel","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/4df8cfc155402a2928d11f80b0220037b8bd26c4f1b19c4598d826e0306e6307?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/4df8cfc155402a2928d11f80b0220037b8bd26c4f1b19c4598d826e0306e6307?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/4df8cfc155402a2928d11f80b0220037b8bd26c4f1b19c4598d826e0306e6307?s=96&d=mm&r=g","caption":"Israel"},"url":"https:\/\/www.griddb.net\/en\/author\/israel\/"}]}},"_links":{"self":[{"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/posts\/55642","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/comments?post=55642"}],"version-history":[{"count":2,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/posts\/55642\/revisions"}],"predecessor-version":[{"id":55648,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/posts\/55642\/revisions\/55648"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/media\/55650"}],"wp:attachment":[{"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/media?parent=55642"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/categories?post=55642"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/tags?post=55642"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}