AR.IO LogoAR.IO Documentation

Storing DePIN Data on Arweave Using Turbo

DePIN networks require scalable and cost-effective storage solutions they can trust. With vast amounts of data generated by decentralized physical infrastructure networks, traditional on-chain storage is prohibitively expensive, yet networks need reliable, long-term access to their device data.

Arweave via AR.IO Network provides chain-agnostic, permanent and immutable storage for a one-time fee, ensuring networks can access any device data previously stored and verify it has not been tampered with.

Getting Started with DePIN Data Storage

Prepare Your Data Structure

Organize your DePIN device data in a consistent format. Here's an example for environmental sensor data:

{
  "device_id": "airmon-007",
  "timestamp": "2025-09-22T14:31:05Z",
  "location": { "lat": 51.5098, "lon": -0.118 },
  "pm25": 16,
  "co2_ppm": 412,
  "noise_dB": 41.2
}

Best Practices:

  • Use consistent field names across all devices
  • Include timestamps in ISO format
  • Add device identifiers for tracking
  • Consider data compression for large datasets

Tag Your Data for Discovery

Proper tagging is essential for finding your data later. Consider these tags for DePIN data:

{
  "name": "App-Name",
  "value": "AirQuality-DePIN-v1.0"
},
{
  "name": "Device-ID",
  "value": "airmon-007"
},
{
  "name": "Device-Type",
  "value": "Environmental-Sensor"
},
{
  "name": "Network-Name",
  "value": "AirQuality-Network"
},
{
  "name": "Data-Category",
  "value": "Air-Quality"
},
{
  "name": "Location",
  "value": "London-UK"
},
{
  "name": "Device-Timestamp",
  "value": "2025-09-22T14:31:05Z"
}

Tagging Strategy:

  • Use consistent naming conventions
  • Include geographic identifiers
  • Add device type classifications
  • Include data categories for filtering

For more detailed information on tagging, see our Tagging documentation

Upload to Arweave

Select the best method for your DePIN network's needs:

import { TurboFactory } from '@ardrive/turbo-sdk'

// Initialize with your wallet
const turbo = await TurboFactory.authenticated({
  privateKey: jwk, // Your Arweave wallet
  token: 'arweave'
})

// Upload device data
const result = await turbo.upload({
  data: JSON.stringify(deviceData),
  dataItemOpts: {
    tags: [
      { name: "Content-Type", value: "application/json" },
      { name: "App-Name", value: "AirQuality-DePIN-v1.0" },
      { name: "Device-ID", value: "airmon-007" },
      { name: "Device-Type", value: "Environmental-Sensor" },
      { name: "Network-Name", value: "AirQuality-Network" },
      { name: "Data-Category", value: "Air-Quality" },
      { name: "Location", value: "London-UK" },
      { name: "Device-Timestamp", value: "2025-09-22T14:31:05Z" }
    ]
  }
})
# Install Turbo CLI
npm install -g @ardrive/turbo-sdk

# Upload a single file
turbo upload-file --file-path sensor-data.json \
  --tag "Content-Type:application/json" \
  --tag "App-Name:AirQuality-DePIN-v1.0" \
  --tag "Device-Type:Environmental-Sensor" \
  --tag "Network-Name:AirQuality-Network" \
  --tag "Data-Category:Air-Quality" \
  --tag "Location:London-UK" \
  --tag "Device-Timestamp:2025-09-22T14:31:05Z"

# Upload entire folder
turbo upload-folder --folder-path ./sensor-data \
  --tag "App-Name:AirQuality-DePIN-v1.0" \
  --tag "Network-Name:AirQuality-Network" \
  --tag "Data-Category:Air-Quality" \
  --index-file index.json

For more advanced uploading options, see our Advanced Uploading with Turbo guide, or the Turbo SDK documentation directly.

Querying Your DePIN Data

Find Your Data

Use GraphQL to search for your DePIN data by tags and criteria:

# Find all data for a specific device, most recent results first
query {
  transactions(
    tags: [
      { name: "App-Name", values: ["AirQuality-DePIN-v1.0"] }
      { name: "Device-ID", values: ["airmon-007"] }
    ]
    first: 100
    sort: HEIGHT_DESC
  ) {
    edges {
      node {
        id
        tags {
          name
          value
        }
        data {
          size
        }
      }
    }
  }
}
# Find data by location
query {
  transactions(
    tags: [
      { name: "App-Name", values: ["AirQuality-DePIN-v1.0"] }
      { name: "Location", values: ["London-UK"] }
    ]
    first: 50
  ) {
    edges {
      node {
        id
        tags {
          name
          value
        }
      }
    }
  }
}

For more advanced querying options, see our Find Your Data documentation.

Access and Use Your Data

Once you have transaction IDs from your queries, choose how to fetch and process the data:

Direct data fetching:

// Example: Process air quality data
async function processAirQualityData(transactionIds) {
  const results = []

  for (const txId of transactionIds) {
    const response = await fetch(`https://arweave.net/${txId}`)
    const data = await response.json()

    // Process the data
    const processed = {
      Device_ID: data.device_id,
      timestamp: data.timestamp,
      location: data.location,
      pm25: data.pm25,
      co2_ppm: data.co2_ppm,
      noise_dB: data.noise_dB
    }

    results.push(processed)
  }

  return results
}

For more information on fetching data, see our Fetch Data documentation.

Verified data with optimized routing:

import {
  createWayfinderClient,
  PreferredWithFallbackRoutingStrategy,
  FastestPingRoutingStrategy,
  HashVerificationStrategy
} from "@ar.io/wayfinder-core";
import { ARIO } from '@ar.io/sdk';

const wayfinder = createWayfinderClient({
  ario: ARIO.mainnet(),
  routingStrategy: new PreferredWithFallbackRoutingStrategy({
    preferredGateway: 'https://your-gateway.com',
    fallbackStrategy: new FastestPingRoutingStrategy({ timeoutMs: 500 }),
  }),
  verificationStrategy: new HashVerificationStrategy({
    trustedGateways: ['https://arweave.net'],
  }),
  telemetrySettings: {
    enabled: true,
    clientName: 'AirQuality-DePIN-v1.0',
  },
});

// Fetch and verify data using ar:// protocol
async function processVerifiedAirQualityData(transactionIds) {
  const results = []

  for (const txId of transactionIds) {
    const response = await wayfinder.request(`ar://${txId}`)
    const data = await response.json()

    // Process the verified data
    const processed = {
      Device_ID: data.device_id,
      timestamp: data.timestamp,
      location: data.location,
      pm25: data.pm25,
      co2_ppm: data.co2_ppm,
      noise_dB: data.noise_dB,
      noise_level: data.noise_dB,
      verified: true // Data is cryptographically verified
    }

    results.push(processed)
  }

  return results
}

Learn more about data verification with Wayfinder.

Next Steps

In production, teams have several options to take this further to provide significantly more value to the network and its users including:

These approaches can make your DePIN data even more resilient and useful. See more detailed guides about this below and or join our discord to find out more.

Need Help?

If you're interested in exploring these advanced features for your DePIN network, join our Discord community or reach out to our team.

How is this guide?