Skip to main content

8 posts tagged with "architecture"

View All Tags

Validating Portability: The Vending Machine Multi-Framework Test

· 2 min read
TeaQL Team
Core Team

One of the core philosophies of TeaQL is that business logic and data schemas should be completely decoupled from the web framework. To put this to the test, we recently conducted an end-to-end validation using our standard vending-machine-service example across the three major Java frameworks.

The results successfully demonstrated the power of declarative data models.

TeaQL Java Runtime: Modular Refactor, Multi-Framework Ready, Rust-Aligned

· 6 min read
Philip Z
Architect

We refactored the TeaQL Java runtime (teaql-java) to achieve three goals:

  1. JPMS module boundaries — seal internal packages, expose only what generated code needs
  2. Spring Boot independence — run without Spring Boot using a plain main() function
  3. Rust alignment — dual-layer audit logging, compile-time query enforcement, RequestPolicy

Unveiling TeaQL Architecture: Declarative Multi-Destination Data Service Routing — Farewell to the 'Glue Code' of Polyglot Persistence

· 5 min read
TeaQL Team
Core Team

In modern complex application architectures, polyglot persistence has almost become a standard configuration. Within a single system, core transactional data may require PostgreSQL for strong consistency guarantees, massive execution logs might need Meilisearch for full-text search, state information could be thrown into Redis for ultra-high-speed caching, and local development might even downgrade to rusqlite.

However, while enjoying the ultimate performance of multi-destination storage, we often find ourselves trapped in a painful "code swamp."

Kernel-Level Audit & Privacy: Building Resilient Audit Chains in the AI Coding Era

· 6 min read
Philip Z
Architect

In the era of AI Coding, business code may be co-generated and modified by human developers, AI agents, or automated tools. This brings a new challenge:

While business logic is becoming increasingly easy to generate automatically, the audit chain must not become fragile as a result.

Traditional audit systems often rely on business code to actively record logs. However, in AI Coding scenarios, this approach carries clear risks:

  • AI might forget to write audit logs;
  • AI might accidentally disable logs;
  • AI might generate code that bypasses audits;
  • Business code might unintentionally record sensitive plain text;
  • A custom audit hook might access raw data it shouldn't see;
  • Long strings, JSON payloads, or execution logs might cause audit log bloating or even out-of-memory (OOM) errors.

Therefore, TeaQL underwent a low-level refactoring to move auditing capabilities into the framework kernel rather than leaving them entirely to the business code. We established the following core principles:

Audit must be kernel-level.
Business code may enrich audit trails, but it cannot erase them.
Sensitive fields do not disappear; only their plain text disappears.

The Return of E Expressions: Fluent Chaining and Structured Panics for AI Auto-Healing

· 4 min read
Philip Z
Architect

In the evolution of TeaQL, we've constantly navigated the tension between developer ergonomics and idiomatic Rust. Recently, we made a bold decision: we are bringing back the beloved E:: fluent expression chain to Rust.

But this isn't a simple rollback. We've redesigned it from the ground up with zero-cost reference chaining and introduced a revolutionary structured panic mechanism that turns runtime errors into self-healing instructions for AI agents.

Why AI-generated software needs deterministic business APIs

· 2 min read
TeaQL Code Gen
Core Contributor

AI coding tools can produce useful application code quickly. The problem is not speed. The problem is boundary control.

If an AI tool has to infer persistence behavior from scattered SQL, repositories, mapper XML, DTOs, and service conventions, it will eventually guess wrong.

TeaQL exists to make that boundary deterministic.

The Guessing Problem

When AI writes data-access code directly, it must infer:

  • table names;
  • column names;
  • relation cardinality;
  • tenant filters;
  • permission rules;
  • deleted-row semantics;
  • transaction boundaries;
  • pagination rules;
  • response shape;
  • database dialect differences.

Some of these guesses can pass a simple test and still be wrong in production.

The Business API Boundary

TeaQL generates APIs from the domain model. That means AI code can compose with named business methods instead of inventing storage behavior.

let orders = Q::orders().select_customer_with(Q::customers().comment("Query customers").purpose("Load data").select_name())
.select_line_item_list_with(Q::line_items().comment("Query line_items").purpose("Load data").select_sku())
.which_statuses_are("PAID")
.page(1, 20)
.comment("Query orders").purpose("Load data")
.execute_for_list(&ctx)
.await?;

The model controls what fields and relations exist. The runtime controls how the query executes. The AI composes within those boundaries.

Deterministic Does Not Mean Rigid

A deterministic API can still be expressive:

  • filters can be combined;
  • relation loads can be nested;
  • aggregates can be grouped;
  • graph writes can save parent and child objects together;
  • provider-specific behavior can be selected below the API.

The point is that the API surface is stable and reviewable.

Better Prompts

TeaQL also makes prompts smaller.

Instead of giving an AI tool the entire schema, SQL examples, repository conventions, and DTO rules, a team can provide a generated API guide:

Use TeaQL Q APIs for reads.
Use generated relation selectors.
Execute through UserContext.
Do not write raw SQL unless explicitly requested.
Use graph save for parent-child persistence.

That is a stronger contract than a long explanation of database structure.

Runtime Safety

The generated API is only half the story. Runtime boundaries matter too.

TeaQL keeps execution behind context and provider layers:

  • Java uses UserContext as the runtime boundary.
  • Rust uses teaql_runtime::UserContext, repository registries, behavior hooks, and provider registration.
  • Database providers execute against PostgreSQL, MySQL, SQLite, rusqlite, or memory.

AI-generated application code should not own those decisions.

The Short Version

AI tools are fast at composition. They are unreliable at reconstructing business rules from infrastructure code.

TeaQL gives them deterministic business APIs to compose.

Core Architecture Refactor: Modularization and Reactive Support

· One min read
TeaQL Code Gen
Core Contributor

TeaQL core was decoupled from Spring, the SQL repository became its own module, and WebFlux reactive support was added.

Module Split

Before

teaql (monolithic)
├── Entity/Request/Context
├── SQLRepository (all databases)
└── Spring auto-config

After

teaql (core, no Spring dependency)
├── Entity/Request/Context
├── Expression framework
└── Checker

teaql-sql (SQL repository base)
teaql-mysql / teaql-pg / teaql-oracle (database-specific)
teaql-autoconfigure (Spring Boot starter)

WebFlux Support

+ WebFlux reactive endpoint support
- Removed spring-boot-starter-web dependency from core

TeaQL now works with both Spring MVC and Spring WebFlux.

JDBC DataSource

Added JdbcDataSource for explicit JDBC connection management.

TeaQL is Born: Type-Safe Query Expressions

· One min read

This is where TeaQL began. In November 2022, the core runtime shipped with 95 files and 4,636 lines of code.

Core Capabilities

SQL Expression Parser

SQLExpressionParser, PropertyParser, and RawSqlParser form the foundation of type-safe query expressions:

Q.orders().filter(
Q.orders().comment("Query orders").purpose("Load data").customer().city().eq("Shanghai")
).comment("Query orders").purpose("Load data").executeForList(ctx);

Sub-Query Support

SubQueryParser (62 lines) enables nested queries expressed naturally in Java:

Q.orders().filter(
Q.orders().comment("Query orders").purpose("Load data").customer().city().eq("Shanghai")
).comment("Query orders").purpose("Load data").executeForList(ctx);

Dynamic Aggregation Framework

SimpleAggregation supports count, sum, avg, and more directly from the domain model.

Architecture at a Glance

  • Expression-based queries: Type-safe Java expressions compiled to SQL
  • Repository pattern: SQLRepository as the base with database-specific extensions
  • Sub-query composition: Nest queries naturally in Java
  • Aggregation framework: First-class aggregate function support

These patterns remain the foundation of TeaQL today.