LDES server implementation guide for developers

Living Document,

Previous Versions:
Editor:
Gerald Haesendonck (Ghent University - imec)

Abstract

This specification aims to be a practical guide for developers to create a Linked Data Event Stream (LDES) server.

1. Introduction

Creating a Linked Data Event Stream (LDES) server involves understanding two specifications, the LDES specification ([ldes-spec]) and the TREE hypermedia specification ([tree-spec]), upon which the LDES specification is built. The goal of this specification is to describe the requirements for a server that hosts a time-based fragmented LDES and provides a mechanism for adding members to an LDES, based on Linked Data Platform concepts.

Note: At this moment this document addresses the requirements of a specific use case. Existing implementations of generic LDES servers are LDES Solid Server and VSDS LDESServer4J.

2. LDES

2.1. Example and definition

This guide uses a running example to explain a Linked Data Event Stream and, in the next chapter, the operations the server supports.

The scenario is a scale that measures weights of a person. The readings are sent to an LDES server which keeps track of every reading.

A reading might look like this:

{
  "sensor": "http://example.com/sensors/weightSensor",
  "value": 78.4,
  "timestamp": "2025-01-01T08:00:00Z",
  "unit": "weightInKg"
}

Definition: A LDES is a collection representing a stream of unmodifiable objects called members.

Here is an example of a minimal LDES with three weight readings as members:

@prefix sosa: <http://www.w3.org/ns/sosa/> .
@prefix ldes: <https://w3id.org/ldes#> .
@prefix tree: <https://w3id.org/tree#> .
@prefix xsd:  <http://www.w3.org/2001/XMLSchema#> .
@prefix sensors: <http://example.com/sensors/> .
@prefix shapes: <http://example.com/shapes/> .

@base <http://example.com/weights/> .

<#EventStream> a ldes:EventStream ;
  ldes:timestampPath sosa:resultTime ;
  tree:shape shapes:memberShape ;
  tree:member <2025/01/weight1>, <2025/01/weight2>, <2025/02/weight3> .

<2025/01/weight1>
  a sosa:Observation ;
  sosa:madeBySensor sensors:weightSensor ;
  sosa:hasSimpleResult "78.4"^^xsd:decimal ;
  sosa:observedProperty: "weightInKg" ;
  sosa:resultTime "2025-01-01T08:00:00Z"^^xsd:dateTime .

<2025/01/weight2>
  a sosa:Observation ;
  sosa:madeBySensor sensors:weightSensor ;
  sosa:hasSimpleResult "78.6"^^xsd:decimal ;
  sosa:observedProperty: "weightInKg" ;
  sosa:resultTime "2025-01-15T08:00:00Z"^^xsd:dateTime .

<2025/02/weight3>
  a sosa:Observation ;
  sosa:madeBySensor sensors:weightSensor ;
  sosa:hasSimpleResult "78.1"^^xsd:decimal ;
  sosa:observedProperty: "weightInKg" ;
  sosa:resultTime "2025-02-01T07:15:00Z"^^xsd:dateTime .

Example 1 is formatted in Turtle [TURTLE], a compact human-readable serialisation of RDF [RDF-CONCEPTS], a graph-based data model for linked data. The same information could also be formatted in JSON for linking data [JSON-LD]:

{
   "@context" : {
      "@base": "http://example.com/weights/"
      "ldes" : "https://w3id.org/ldes#",
      "sensor" : {
         "@id" : "http://www.w3.org/ns/sosa/madeBySensor",
         "@type" : "@id"
      },
      "sosa" : "http://www.w3.org/ns/sosa/",
      "timestamp" : {
         "@id" : "http://www.w3.org/ns/sosa/resultTime",
         "@type" : "http://www.w3.org/2001/XMLSchema#dateTime"
      },
      "tree" : "https://w3id.org/tree#",
      "unit" : "http://www.w3.org/ns/sosa/observedProperty",
      "value" : "http://www.w3.org/ns/sosa/hasSimpleResult",
      "xsd" : "http://www.w3.org/2001/XMLSchema#",
      "sensors": "http://example.com/sensors/",
      "shapes": "http://example.com/shapes/"
   },
   "@graph" : [
      {
         "@id" : "#EventStream",
         "@type" : "ldes:EventStream",
         "ldes:timestampPath" : {"@id" : "sosa:resultTime"},
         "tree:shape": {"@id": "shapes:memberShape"},
         "tree:member" : [
           {"@id" : "2025/01/weight1"},
           {"@id" : "2025/01/weight2"},
           {"@id" : "2025/02/weight3"}
         ]
      },
      {
         "@id" : "2025/01/weight1",
         "@type" : "sosa:Observation",
         "sensor" : "sensors:weightSensor",
         "value" : 78.4,
         "timestamp" : "2025-01-01T08:00:00Z",
         "unit" : "weightInKg"
      },
      {
         "@id" : "2025/01/weight2",
         "@type" : "sosa:Observation",
         "value" : 78.6,
         "sensor" : "sensors:weightSensor",
         "timestamp" : "2025-01-15T08:00:00Z",
         "unit" : "weightInKg"
      },
      {
         "@id" : "2025/02/weight3",
         "@type" : "sosa:Observation",
         "value" : 78.1,
         "sensor" : "sensors:weightSensor",
         "timestamp" : "2025-02-01T07:15:00Z",
         "unit" : "weightInKg"
      }

   ]
}

The context (@context) maps terms to IRIs [IRI] (necessary for Linked data). The @graph contains the data itself. Thanks to the term mapping in the context, the members of the LDES almost look identical to the original readings in JSON.

Throughout this document Turtle and JSON-LD serialisations will be used.

Conformance

Conformance requirements are expressed with a combination of descriptive assertions and RFC 2119 terminology. The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in the normative parts of this document are to be interpreted as described in RFC 2119. However, for readability, these words do not appear in all uppercase letters in this specification.

All of the text of this specification is normative except sections explicitly marked as non-normative, examples, and notes. [RFC2119]

Examples in this specification are introduced with the words “for example” or are set apart from the normative text with class="example", like this:

This is an example of an informative example.

Informative notes begin with the word “Note” and are set apart from the normative text with class="note", like this:

Note, this is an informative note.

Index

Terms defined by this specification

References

Normative References

[IRI]
M. Duerst; M. Suignard. Internationalized Resource Identifiers (IRIs). January 2005. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc3987
[JSON-LD]
Manu Sporny; Gregg Kellogg; Markus Lanthaler. JSON-LD 1.0. 3 November 2020. REC. URL: https://www.w3.org/TR/json-ld/
[LDES-SPEC]
Pieter Colpaert. Linked Data Event Streams. URL: https://w3id.org/ldes/specification
[RDF-CONCEPTS]
Graham Klyne; Jeremy Carroll. Resource Description Framework (RDF): Concepts and Abstract Syntax. URL: https://w3c.github.io/rdf-concepts/spec/
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://datatracker.ietf.org/doc/html/rfc2119
[TREE-SPEC]
Pieter Colpaert. The TREE hypermedia specification. URL: https://w3id.org/tree/specification
[TURTLE]
Eric Prud'hommeaux; Gavin Carothers. RDF 1.1 Turtle. URL: https://w3c.github.io/rdf-turtle/spec/