DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Newsletter
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • Building Time-Series Applications With Java and InfluxDB
  • Dynamic Arrays, Spill, and LET: What Changed in Excel and Why It Matters for Java Applications
  • OBO SSO in Java Applications: Securely Calling Downstream APIs on Behalf of a User
  • Using Java for Developing Agentic AI Applications: The Enterprise-Ready Stack in 2026

Trending

  • Wasm Inside Neo4j: Building the Example That Didn't Exist
  • The Startup Time Trick Hiding Inside Your Docker Build
  • The Context Window Trap: Why More Context Doesn’t Mean Better AI
  • AI-Powered API Development With Spring AI
  1. DZone
  2. Coding
  3. Java
  4. Building High-Performance Time-Series Applications With Java and QuestDB

Building High-Performance Time-Series Applications With Java and QuestDB

QuestDB combines fast time-series ingestion with a familiar SQL model. With Eclipse JNoSQL 1.1.18, Java developers can use it through TimeSeriesTemplate and Jakarta Data.

By 
Otavio Santana user avatar
Otavio Santana
DZone Core CORE ·
Oct. 07, 26 · Tutorial
Likes (0)
Comment
Save
Tweet
Share
80 Views

Join the DZone community and get the full member experience.

Join For Free

QuestDB is well-suited for applications necessitating high-performance ingestion and SQL access to time-oriented data. It is especially useful in financial markets, real-time analytics, observability, telemetry, and operational systems where data arrives continuously and must be queried with low latency. Unlike general-purpose databases, QuestDB is purpose-built with time as a core element of both storage and query processes.

QuestDB appeals to enterprise developers by combining a time-series architecture with a familiar SQL interface. This technique reduces the learning curve for teams experienced in relational querying while providing a database optimized for append-heavy, chronological workloads. For systems needing recent-state queries, historical analysis, trend detection, and rapid ingestion, QuestDB delivers a practical solution.

Why QuestDB Matters

QuestDB excels when applications require both high ingestion rates and fast analytical queries on recent and historical data. This is essential for workloads with continuous data streams where rapid business response is critical, such as market prices, trading activity, telemetry, infrastructure metrics, clickstream data, operational events, and real-time business indicators. In these cases, the database must efficiently manage append-heavy data while supporting intuitive SQL queries across time ranges.

As a result, QuestDB is well suited for financial platforms, observability systems, logistics, energy, IoT, and real-time analytics. For example, a trading system can query both the latest prices and historical intervals, an operations platform can analyze recent latency and throughput, and a logistics application can review vehicle or delivery telemetry over time. Its SQL-oriented model is especially valuable for enterprise teams, offering a familiar query language alongside an architecture designed for time-series workloads.

Hands-On: Java With QuestDB

We will build a simple Java application using QuestDB as the time-series database. For development, the easiest way to begin is with Docker:

Shell
 
docker run -d \
  --name questdb-instance \
  -p 9000:9000 \
  questdb/questdb:10.0.1


QuestDB provides its Web Console and HTTP endpoint on port 9000. Once the container is running, you can open http://localhost:9000 in your browser to view the data.

Configuring the Application

Eclipse JNoSQL uses Jakarta APIs such as CDI and JSON-B, along with Eclipse MicroProfile Config. These APIs are available in popular Java runtimes including Helidon, Quarkus, Payara, and Open Liberty.

Add the QuestDB driver dependency:

XML
 
<dependency>
    <groupId>org.eclipse.jnosql.databases</groupId>
    <artifactId>jnosql-questdb</artifactId>
    <version>${jnosql.version}</version>
</dependency>


Next, configure the Time Series database and QuestDB connection in microprofile-config.properties:

Properties files
 
jnosql.timeseries.database=qdb
jnosql.questdb.url=ws::addr=localhost:9000


The qdb value specifies the logical database for the JNoSQL Time Series manager. The QuestDB URL uses the connection format required by the driver.

Modeling Sensor Data

For this example, we will use a simple sensor reading model:

Java
 
@Entity
public class SensorReading {

    @Id
    private Instant id;

    @Column
    private String sensor;

    @Column
    private double temperature;

    @Column
    private double humidity;

    // constructors, getters, and setters
}


The Instant field records the measurement time, while the other fields describe the sensor reading at that moment.

You can also expose the entity through Jakarta Data:

Java
 
@Repository
public interface SensorReadingRepository
        extends BasicRepository<SensorReading, Instant> {

    List<SensorReading> findBySensorOrderByIdDesc(
            String sensor,
            Limit limit);
}


Using TimeSeriesTemplate

You can now insert a sequence of readings and query both the latest state and recent history:

Java
 
public class App {

    public static void main(String[] args) {

        var firstReading = new SensorReading(
                Instant.parse("2026-09-20T08:00:00Z"),
                "sensor-01",
                21.4,
                45.0
        );

        var secondReading = new SensorReading(
                Instant.parse("2026-09-20T09:00:00Z"),
                "sensor-01",
                22.1,
                46.5
        );

        var latestReading = new SensorReading(
                Instant.parse("2026-09-20T10:15:00Z"),
                "sensor-01",
                23.6,
                48.2
        );

        try (SeContainer container =
                     SeContainerInitializer.newInstance().initialize()) {

            TimeSeriesTemplate template =
                    container.select(TimeSeriesTemplate.class).get();

            template.insert(firstReading);
            template.insert(secondReading);
            template.insert(latestReading);

            var currentReading = template
                    .select(SensorReading.class)
                    .where("sensor")
                    .eq("sensor-01")
                    .orderBy("id")
                    .desc()
                    .limit(1)
                    .singleResult();

            System.out.println(
                    "Current sensor reading: " + currentReading
            );

            var history = template
                    .select(SensorReading.class)
                    .where("sensor")
                    .eq("sensor-01")
                    .orderBy("id")
                    .desc()
                    .skip(1)
                    .limit(10)
                    .result();

            System.out.println("Recent sensor history:");
            history.forEach(System.out::println);
        }
    }
}


The first query retrieves the latest reading for sensor-01. The second retrieves a limited history, skipping the most recent observation. This approach better fits typical time-series use cases than retrieving records by identifier.

Using Jakarta Data

You can achieve the same functionality using a Jakarta Data repository:

Java
 
public class App2 {

    public static void main(String[] args) {

        var firstReading = new SensorReading(
                Instant.parse("2026-09-20T08:00:00Z"),
                "sensor-01",
                21.4,
                45.0
        );

        var secondReading = new SensorReading(
                Instant.parse("2026-09-20T09:00:00Z"),
                "sensor-01",
                22.1,
                46.5
        );

        var latestReading = new SensorReading(
                Instant.parse("2026-09-20T10:15:00Z"),
                "sensor-01",
                23.6,
                48.2
        );

        try (SeContainer container =
                     SeContainerInitializer.newInstance().initialize()) {

            SensorReadingRepository repository =
                    container.select(SensorReadingRepository.class).get();

            repository.save(firstReading);
            repository.save(secondReading);
            repository.save(latestReading);

            var currentReading = repository
                    .findBySensorOrderByIdDesc(
                            "sensor-01",
                            Limit.of(1)
                    )
                    .stream()
                    .findFirst();

            System.out.println(
                    "Current sensor reading: " + currentReading
            );

            var history = repository
                    .findBySensorOrderByIdDesc(
                            "sensor-01",
                            Limit.range(2, 10)
                    );

            System.out.println("Recent sensor history:");
            history.forEach(System.out::println);
        }
    }
}


Notably, QuestDB’s time-series capabilities are available through the same Java programming model as other NoSQL time-series drivers. This lets the application focus on temporal queries such as latest state, ordering, and recent history, while the driver handles database-specific details.

Why SQL Matters for QuestDB Adoption

QuestDB stands out for its time-series specialization and SQL-oriented approach. When organizations adopt specialized databases, teams often struggle to learn new query languages and mental models. By providing a familiar SQL interface, QuestDB helps reduce these adoption barriers.

Teams are already familiar with filtering, ordering, grouping, aggregation, and limiting result sets. Keeping these concepts allows programmers to focus on time-based challenges instead of learning a new query system. This is especially valuable when multiple roles need access to the same data.

Financial systems illustrate this well. Market data, exchange rates, trades, and price movements are time-oriented, and many financial professionals already use SQL extensively. QuestDB lets teams leverage existing SQL expertise while gaining from a database optimized for high-frequency ingestion and time-based analysis.

This advantage also applies to observability and operational analytics. Teams often need to query metrics for example request latency, throughput, error rates, or customer activity over specific intervals. Using familiar SQL constructs makes it easier to access application data for analysis.

QuestDB does not function exactly like a traditional relational database. Its architecture and optimizations target time-series workloads. The result is an approachable query experience combined with a storage engine designed for specialized performance.

For enterprises, this combination is powerful: specialized time-series performance without requiring teams to abandon the familiar query model.

Conclusion

QuestDB is a strong fit for applications that need fast ingestion, recent-state queries, historical analysis, and SQL over continuously changing data. With Eclipse JNoSQL 1.1.18, Java developers can use these capabilities through familiar Jakarta APIs, keeping the application model consistent while QuestDB handles the time-series specialization underneath.

Time series applications Java (programming language)

Opinions expressed by DZone contributors are their own.

Related

  • Building Time-Series Applications With Java and InfluxDB
  • Dynamic Arrays, Spill, and LET: What Changed in Excel and Why It Matters for Java Applications
  • OBO SSO in Java Applications: Securely Calling Downstream APIs on Behalf of a User
  • Using Java for Developing Agentic AI Applications: The Enterprise-Ready Stack in 2026

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook