Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
LABS
Guides

How to Implement Real-Time Port Congestion Data Feeds

This guide details the technical process of building an oracle to deliver real-time port congestion and berth availability data to blockchain applications.
Chainscore © 2026
introduction
TUTORIAL

How to Implement Real-Time Port Congestion Data Feeds

A technical guide for developers on sourcing, processing, and integrating live maritime port congestion data into applications.

Real-time port congestion data provides critical visibility into global supply chain bottlenecks by tracking vessel wait times, berth availability, and terminal throughput. For developers, implementing these feeds involves connecting to specialized data providers like MarineTraffic, VesselFinder, or PortXchange via their APIs. These services aggregate AIS (Automatic Identification System) signals, port authority schedules, and terminal operator data to calculate congestion metrics such as average waiting time (AWT) and queue length. Access typically requires an API key, with data returned in JSON format for easy integration into dashboards, logistics platforms, or analytic models.

The core technical challenge is processing the raw, high-frequency data stream into actionable insights. A common architecture involves a backend service that polls the provider's REST API or subscribes to a WebSocket feed. Incoming data must be parsed, normalized (e.g., converting timestamps to UTC, standardizing port codes like UN/LOCODE), and often enriched with metadata. For example, you might join a vessel's reported position with a static database to determine its size class, as congestion impact differs for a Panamax container ship versus a small bulk carrier. Implementing data validation and caching layers is crucial to handle API rate limits and ensure application resilience.

Here is a basic Node.js example using the axios library to fetch congestion data for the port of Rotterdam (NLRTM) from a hypothetical API, demonstrating the typical request/response pattern:

javascript
const axios = require('axios');
const API_KEY = 'your_api_key_here';
const PORT_CODE = 'NLRTM';

async function getPortCongestion(portCode) {
  try {
    const response = await axios.get(
      `https://api.congestionprovider.com/v1/ports/${portCode}/metrics`,
      { headers: { 'Authorization': `Bearer ${API_KEY}` } }
    );
    // Example response structure
    console.log({
      port: response.data.portName,
      avgWaitHours: response.data.metrics.averageWaitTime,
      vesselsInQueue: response.data.metrics.vesselsWaiting,
      updatedAt: response.data.timestamp
    });
  } catch (error) {
    console.error('Failed to fetch congestion data:', error.message);
  }
}

getPortCongestion(PORT_CODE);

For production systems, consider moving beyond simple polling to an event-driven architecture. You can use message brokers like Apache Kafka or cloud services (AWS EventBridge, Google Pub/Sub) to decouple data ingestion from application logic, allowing multiple services to react to congestion alerts. Key metrics to expose include dwell time (time from arrival to berth), turnaround time (total port stay), and predictive indicators like estimated time of berthing (ETB). Implementing historical data storage in a time-series database (e.g., InfluxDB, TimescaleDB) enables trend analysis and anomaly detection, such as identifying if current wait times exceed the 90th percentile for a given port.

Finally, integrate the processed data into your user-facing application. This could be a live map using Mapbox GL JS or Leaflet to visualize queue locations, a dashboard with Grafana showing key performance indicators, or automated alerts sent via Slack or email when thresholds are breached. Ensure your implementation accounts for data licensing terms, maintains clear attribution, and includes unit tests for data parsing logic. By building a robust data pipeline, you create a foundational service that can power logistics optimization, freight pricing models, and supply chain risk assessments.

prerequisites
BUILDING THE FOUNDATION

Prerequisites and System Architecture

Before implementing real-time port congestion data feeds, you need the right tools and a clear architectural plan. This section outlines the essential prerequisites and a modular system design for building a reliable on-chain data pipeline.

To build a system that ingests, processes, and publishes real-world port congestion data on-chain, you'll need proficiency in several core technologies. You must be comfortable with a backend language like Python or Node.js for data fetching and API integration. A solid understanding of blockchain fundamentals and smart contract development in Solidity is required for the on-chain component. Familiarity with oracle protocols such as Chainlink Functions or Pyth Network is crucial for secure data delivery. Finally, you'll need access to a reliable data source, such as a maritime API from MarineTraffic or Ports.com, which provides vessel AIS data and port call schedules.

The system architecture follows a modular, off-chain to on-chain design pattern to ensure reliability and decentralization. The first component is the Data Fetcher, an off-chain service (e.g., a serverless function or dedicated microservice) that periodically queries external maritime APIs. It parses the raw JSON responses to extract key metrics like average waiting time, number of vessels at anchor, and berth occupancy rates. This service should include logic for error handling, data validation, and rate limiting to manage API constraints and ensure data quality before further processing.

The processed data is then passed to the Oracle Service, which acts as the bridge to the blockchain. Using a service like Chainlink Functions, you can deploy a script that receives the formatted data from your fetcher, packages it, and initiates an on-chain transaction. The oracle cryptographically attests to the data's integrity off-chain before submitting it. This layer abstracts away the complexities of gas management, transaction signing, and network compatibility, providing a standardized way to push data onto multiple supported chains like Ethereum, Arbitrum, or Polygon.

On the blockchain, the final component is the Data Consumer Smart Contract. This contract, deployed by you, contains the logic to receive and store the updated data from the oracle. It will have a function (e.g., updatePortCongestion) that is callable only by the authorized oracle address. Upon receiving a new data payload, the contract validates the sender, emits an event with the new metrics, and updates its public state variables. Downstream DeFi applications, such as freight futures platforms or insurance protocols, can then read this on-chain state to trigger settlements or adjust risk parameters in real time.

A critical consideration is system reliability and cost. The off-chain fetcher must be highly available, which may require deployment on a cloud platform with auto-scaling. Each on-chain update incurs gas costs, so you must optimize data update frequency and payload size. Implementing a heartbeat or staleness check in your consumer contract is essential; if data is not updated within a expected timeframe, the contract can revert to a safe default state or pause operations to prevent the use of outdated information.

data-sourcing
DATA ACQUISITION

Step 1: Sourcing Raw Data from Maritime Systems

This guide details the technical methods for acquiring real-time port congestion data from primary maritime sources, including AIS, port APIs, and terminal operating systems.

Real-time port congestion analysis begins with sourcing raw data from three primary maritime systems: Automatic Identification System (AIS), Port Community System (PCS) APIs, and Terminal Operating Systems (TOS). AIS transponders on vessels broadcast positional data (latitude, longitude, speed, heading) and voyage information (destination, ETA) via VHF radio. This data is aggregated by terrestrial networks and satellite providers like Spire Maritime or Orbcomm, which offer commercial APIs for programmatic access. For congestion metrics, you need to filter AIS feeds for vessels whose reported destination matches a target port and whose speed indicates they are anchored or drifting in a waiting area.

While AIS provides vessel location, Port Authority APIs deliver operational status. Major global ports like Rotterdam (Portbase), Singapore (Portnet), and Los Angeles (Port Optimizer) offer RESTful APIs with data on berth occupancy, anchorage queue counts, and estimated wait times. Authentication typically requires a registered developer account and an API key. The data schema often includes timestamps, terminal IDs, vessel IMO numbers, and status codes (e.g., BERTHED, ANCHORED, PILOT_ORDERED). This data is crucial for verifying the "why" behind an AIS signal showing a stationary vessel.

The most granular data comes from direct integration with Terminal Operating Systems like NAVIS N4 or Kaleris. These systems manage the real-time movement of containers and equipment within a terminal, providing metrics on crane productivity, gate-in/gate-out truck times, and yard occupancy. Access is usually granted via a secure VPN and a SOAP or REST API provided to authorized partners. A key data point is the berth window, which shows scheduled vs. actual vessel arrival and departure times, directly indicating delays. Parsing this data requires mapping terminal-specific field names to a normalized schema for your application.

To build a reliable feed, you must implement robust data ingestion. For AIS, use a WebSocket or MQTT client to connect to a provider's stream, applying geofencing logic to isolate events near your port polygons. For port and TOS APIs, schedule HTTPS requests with exponential backoff retry logic for handling rate limits. All raw data should be timestamped and written to a durable datastore like a time-series database (e.g., TimescaleDB) or object storage (e.g., Amazon S3) in its original format. This preserves data provenance for later validation and transformation.

A critical technical challenge is data latency and synchronization. AIS data can be delayed by minutes via satellite. Port API updates may be batch-processed hourly. Your ingestion pipeline must tag each record with a source_timestamp and a received_timestamp to calculate freshness. Implement heartbeat checks and alerting for stalled data streams. Furthermore, vessel identities must be reconciled across sources using the IMO number (a unique, permanent identifier) rather than the vessel name or MMSI, which can change.

Finally, consider the legal and compliance framework. AIS data is public, but commercial redistribution of raw feeds may violate provider terms. Port and TOS data is almost always confidential and subject to strict data-sharing agreements covering usage, storage, and anonymization. Before production, ensure your data sourcing methods comply with GDPR, CCPA, and the specific contractual obligations of your data providers. The next step is processing this raw data into structured, analyzable congestion metrics.

data-processing
IMPLEMENTING REAL-TIME FEEDS

Processing and Aggregating Data

This guide explains how to process raw port data into structured, real-time congestion feeds suitable for on-chain consumption.

Raw data from AIS receivers and port APIs is often unstructured or arrives at irregular intervals. The first processing step involves data normalization, where we convert timestamps to a standard format (e.g., Unix epoch), standardize location coordinates, and map vessel types to a consistent taxonomy. This creates a clean, uniform dataset. For example, an AIS message might provide a vessel's speed over ground (SOG) and course over ground (COG); we calculate its estimated time to port (ETP) using its distance from the port's anchorage polygon and current speed.

Next, we perform data aggregation to transform individual vessel data into actionable port-level metrics. This involves grouping all vessels associated with a specific port (e.g., within a 20-nautical-mile radius of the port's pilot station) and calculating key congestion indicators. Common metrics include: the total count of vessels at anchor, the average waiting time for vessels at anchor (in hours), and the aggregate deadweight tonnage (DWT) of the waiting fleet. These aggregated metrics provide a more meaningful signal than raw positional data.

To achieve real-time updates, this aggregation logic must run continuously. We implement this using a stream processing framework like Apache Flink or a serverless function (e.g., AWS Lambda) triggered by new data events. The code snippet below shows a simplified aggregation function in Python, calculating the average waiting time for a port. It assumes a stream of normalized vessel events is being processed.

python
def aggregate_port_metrics(vessel_events, port_id):
    port_vessels = [v for v in vessel_events if v['port_id'] == port_id and v['status'] == 'anchored']
    if not port_vessels:
        return None
    avg_wait_hours = sum(v['wait_hours'] for v in port_vessels) / len(port_vessels)
    total_dwt = sum(v['dwt'] for v in port_vessels)
    return {
        'port_id': port_id,
        'timestamp': int(time.time()),
        'vessels_at_anchor': len(port_vessels),
        'avg_wait_hours': avg_wait_hours,
        'total_dwt': total_dwt
    }

The final, critical step is data attestation before publishing the feed. The aggregated metrics must be signed by the data provider's private key to ensure integrity and origin. This creates a verifiable data point that smart contracts can trust. Using a framework like Chainlink Functions or a custom oracle service, the signed data packet is then broadcast to the target blockchain network. The on-chain component, typically a smart contract, will verify the signature against a known public key before accepting and storing the updated congestion value.

oracle-integration
IMPLEMENTATION

Step 3: Building the Oracle Node and Publishing Data

This section details the practical steps to construct a Chainlink oracle node that fetches, processes, and publishes real-time port congestion data on-chain.

The core of your data feed is the oracle node, which runs the custom external adapter you developed in Step 2. You will deploy this adapter and configure a Chainlink node to execute its logic on a schedule. For production, you typically run the node using the official Chainlink Node Docker image, linking it to your adapter's API endpoint. Key configuration in the node's .env file includes your Ethereum RPC URL (e.g., for Sepolia testnet), wallet private key for transaction signing, and the BRIDGE_RESPONSE_URL pointing to your adapter.

With the node operational, you must define the job specification that tells the node what to do and when. This is a JSON document specifying the job type (e.g., directrequest), the adapter's task (like fetch-port-congestion), and the schedule (e.g., a cron job for 0 */1 * * * to run hourly). The job spec also maps the adapter's output—the congestion score and timestamp—to corresponding oracle contract parameters. This creates a reliable, automated pipeline from your data source to the blockchain.

The final step is publishing the data via an on-chain oracle contract, typically a FluxAggregator or FeedRegistry. Your node, upon a job run, will call the submit function on this contract, providing the latest data point. For developers, you can use the Chainlink Functions framework as an alternative for serverless, decentralized computation, which can simplify the process by handling node infrastructure. Whether using a self-hosted node or Functions, successful transactions result in a new, verifiable data point stored on-chain, completing the real-time feed.

smart-contract-consumption
IMPLEMENTATION

Step 4: Consuming the Feed in a Smart Contract

This guide details how to integrate real-time port congestion data into your on-chain application using Chainlink Functions and the Chainscore API.

To consume the port congestion feed, your smart contract must first import the FunctionsClient interface from the Chainlink Functions library. This interface provides the essential fulfillRequest callback function, which receives the API response. The core logic involves storing the requestId from the initial call and handling the decoded data within the callback. You can find the latest FunctionsClient interface on the Chainlink Functions documentation.

Your contract's primary function will encode the API request parameters, send them to the Chainlink Functions router, and pay the required fees. For a port congestion query, the source code parameter must contain the JavaScript that calls the Chainscore API endpoint, such as https://api.chainscore.dev/v1/port-congestion?port_code=USLAX. The args parameter should include your unique Chainscore API key, which you must manage off-chain and pass in securely for the request.

When the request is fulfilled, the raw response bytes are passed to your fulfillRequest function. You must decode this data, which will be in a format like {"port_code": "USLAX", "congestion_level": 7, "timestamp": 1735689600}. Use abi.decode() to parse the bytes into your chosen Solidity struct or separate variables. It is critical to implement robust error handling here to manage empty responses or failed API calls, which may revert the transaction or set a default state.

Once decoded, you can store the congestion data in a public state variable (e.g., mapping(string portCode => CongestionData) public portData) for other contracts to read, or use it immediately in your application logic. For example, a shipping insurance dApp might adjust premium rates dynamically based on a congestion_level above a certain threshold. Emitting an event with the new data is a best practice for off-chain indexers and frontends.

For production deployment, consider gas optimization and security. Store only the necessary data on-chain, such as the integer congestion_level and a timestamp. Validate the msg.sender in your request function to prevent unauthorized usage. Always test the full request-and-fulfill cycle on a testnet like Sepolia using test LINK and API credits before deploying to mainnet.

DATA FEED EVALUATION

Comparison of Port Congestion Data Sources

A technical comparison of primary data sources for building real-time port congestion feeds, assessing reliability, latency, and integration complexity.

Data Source / MetricMarine Traffic APIsAIS Satellite FeedsPort Authority APIsOn-Chain Oracle Feeds (e.g., Chainlink)

Update Frequency

1-5 minutes

~15 minutes

Varies (1 min - 1 hour)

As per request (e.g., 1 hour)

Data Latency

< 10 seconds

2-5 minutes

30 seconds - 5 minutes

Oracle heartbeat + on-chain confirmation

Global Port Coverage

~90% major ports

~98% global coverage

Single port or region

Dependent on node network

Data Granularity

Vessel positions, ETA, berth status

Raw AIS messages (MMSI, SOG, COG)

Official berth/wait times, queue length

Processed data point (e.g., congestion score)

API Reliability (Uptime)

99.5%

99.9%

95-99%

99.9% (oracle network dependent)

Historical Data Access

Integration Complexity (Dev)

Medium (REST/WebSocket)

High (raw data parsing)

Low-Medium (varies by port)

Low (smart contract calls)

Cost Model

Tiered subscription ($500-$5000+/mo)

Enterprise licensing ($10k+/mo)

Often free or low cost

Gas fees + oracle service premium

security-considerations
IMPLEMENTING REAL-TIME DATA FEEDS

Security and Reliability Considerations

Integrating real-time port congestion data into your dApp requires a robust architecture to ensure data integrity and system resilience.

Real-time data feeds introduce unique security vectors. The primary risk is data source manipulation, where an attacker compromises the oracle or API supplying congestion metrics. To mitigate this, implement multi-source validation by aggregating data from at least three independent providers like Chainlink, Pyth, and a custom indexer. Use a medianizer contract to discard outliers and compute a consensus value, preventing any single faulty source from poisoning the feed. This design mirrors the security model of decentralized price oracles used in DeFi protocols like Aave.

Data freshness and liveness are critical for reliability. Implement heartbeat and staleness checks within your smart contracts. For example, a keeper network can monitor the updatedAt timestamp of your data feed; if the last update exceeds a predefined threshold (e.g., 300 seconds for a "real-time" feed), the contract can pause dependent operations or revert to a fallback mode. Use event-driven architectures with services like The Graph for subgraph indexing or Chainlink Functions for serverless computation to trigger updates only when on-chain conditions are met, optimizing for gas efficiency and timeliness.

Ensure end-to-end cryptographic verification. When fetching data off-chain, use signature verification to authenticate the data publisher. Services like Pyth Network provide signed price updates that your contract can verify against a known public key. For custom feeds, consider a commit-reveal scheme where data providers commit a hash of the data and later reveal it, allowing for slashing conditions in a bonded system. This adds a cost to providing incorrect data, aligning incentives as seen in optimistic oracle designs like UMA's.

Design for graceful degradation and fail-safes. Your system should have clearly defined fallback procedures. This could involve switching to a more conservative, time-weighted average price (TWAP) during high volatility or network congestion, or utilizing a decentralized data marketplace like Streamr to source backup feeds. Smart contracts should include circuit breaker patterns and pausable functions controlled by a multisig or DAO vote, allowing manual intervention if automated systems fail, similar to emergency shutdown mechanisms in MakerDAO.

Finally, conduct rigorous testing and monitoring. Use forked mainnet testing with tools like Foundry or Hardhat to simulate real network conditions and oracle failures. Implement off-chain monitoring with alerting systems (e.g., OpenZeppelin Defender, Tenderly Alerts) to track feed latency, deviation, and contract health. Regularly audit the entire data pipeline, from source ingestion to on-chain consumption, and consider bug bounty programs to crowd-source security reviews, as is standard for major protocols like Uniswap and Compound.

DEVELOPER FAQ

Frequently Asked Questions

Common questions and troubleshooting for integrating real-time port congestion data into Web3 applications and supply chain smart contracts.

A real-time port congestion data feed is an oracle-based information stream that provides live metrics on shipping delays at major global ports. It works by aggregating data from multiple sources—including AIS vessel tracking, port authority APIs, and satellite imagery—and delivering it as a verified, on-chain data point.

For developers, this typically involves a decentralized oracle network like Chainlink or API3 querying off-chain data providers. The data is cryptographically signed, aggregated for consensus, and posted to a smart contract on a blockchain (e.g., Ethereum, Polygon). Your dApp can then consume this data via the oracle's on-chain contract, using it to trigger logic in supply chain finance, insurance, or logistics applications.

Key metrics provided include average wait times (in days), queue length (number of vessels), and berth occupancy rates.

conclusion
IMPLEMENTATION SUMMARY

Conclusion and Next Steps

You have learned how to build a real-time port congestion data feed for Web3 applications. This guide covered the core architecture, data sourcing, and on-chain integration.

Implementing a real-time port congestion oracle involves a multi-layered architecture. The off-chain component fetches and processes data from sources like the MarineTraffic API or Port Authority AIS feeds, using a secure runner to compute congestion metrics. The on-chain component, typically a Feed smart contract, receives signed data updates via an update() function, making the latest congestion index available for dApps to query. This separation ensures the heavy computation happens off-chain while providing tamper-resistant, verifiable data on-chain.

For production deployment, focus on reliability and security. Implement a multi-signer setup for data attestation using a framework like Chainlink's DECO or API3's dAPIs to mitigate single points of failure. Your data processing pipeline should include validation checks for anomalies and a fallback mechanism in case of primary API failure. Consider storing historical data on decentralized storage like Arweave or Filecoin for auditability and advanced analytics by your users.

The primary use case is enabling dynamic pricing and logistics in maritime DeFi and NFT projects. For example, a shipping insurance dApp can use the congestion index to adjust premium rates in real-time, while a supply chain NFT representing a cargo container could update its estimated arrival date based on live port conditions. This creates a tangible link between real-world logistics and on-chain financial products.

To extend this system, explore integrating additional data layers. Combining port congestion with weather data feeds, fuel price oracles, and customs clearance status can create a comprehensive maritime data ecosystem. You could also develop a zk-proof circuit to allow users to verify that a specific data point was part of a valid update without revealing the entire dataset, enhancing privacy for proprietary routing strategies.

Next, you should test your implementation thoroughly. Deploy your contracts to a testnet like Sepolia or Polygon Amoy and simulate data updates under various network conditions. Use monitoring tools like Tenderly or OpenZeppelin Defender to track contract events and signer health. The final step is to plan a phased mainnet rollout, starting with a single, non-critical port to validate system performance before full-scale deployment.