Event-Per-Entity Storage: Agent Memory Without Joins

Your agent answers a customer question with total confidence, and it is wrong, because the warehouse row it read was a precomputed aggregate that threw away the sequence of what actually happened. If you build retrieval pipelines for agents, the real question is not which model to use. It's where the event history lives and what shape it's in when the agent asks for it.
A new database, KeewanoDB, makes a sharp architectural bet on this problem, and whether or not you ever use it, the pattern is worth understanding. This post breaks down event-per-entity storage, what the launch claims (and what remains unverified), and how to apply the idea with tools you already run.
What event-per-entity storage actually means
Event-per-entity storage treats each user, device, or agent as a primary key and attaches every event for that entity, in sequence, directly to it. Instead of events scattered across fact tables and linked by foreign keys, each entity owns an ordered stream. KeewanoDB's CEO described this as one large table per entity rather than a system built around joins across many tables.
Here is the contrast in plain terms:
| Aspect | Row/aggregate model (typical warehouse) | Event-per-entity model |
|---|---|---|
| Unit of storage | Row in a table, often pre-aggregated | Ordered event stream owned by one entity |
| Sequence | Reconstructed via timestamps and joins | Native; order is the storage order |
| Context | Lives in other tables, joined at query time | Attached to the event at ingestion |
| Typical agent question | "What's the count/sum?" | "What happened, in what order, and why?" |
| Cross-entity analysis | Natural (joins, group-bys) | Awkward by design |
According to the company, KeewanoDB stores events as four-byte units on disk, sequenced by entity, and uses no joins in queries. Treat the byte-level detail as a vendor description, not an independently verified spec. The shape of the idea is what matters: sequence is the primary organizing principle, not an afterthought.
Why flattened rows fail agents
A flattened row answers "what is the state now," but an agent reasoning about a customer, device, or workflow usually needs "how did it get here." Aggregates and snapshots discard the sequence and context that explain causality, so the agent has to rebuild that history at query time from a warehouse or search index, and it often guesses wrong.
Consider a support agent asked, "Why was this account flagged?" A typical schema gives you:
-- Typical warehouse view: current state only
SELECT account_id, status, last_login, total_orders
FROM accounts
WHERE account_id = 'acct_4821';
-- status = 'flagged', total_orders = 14
That tells the agent the account is flagged. It says nothing about the order of events: that the account was active, went inactive for months, then showed a burst of activity right before the flag. To get that, you reconstruct a timeline from three or four tables, and every join is a chance to pick up the wrong version of a dimension or drop an event.
The practical failure mode is confident wrongness. In a July 2026 VentureBeat Pulse Research survey of 101 enterprises with more than 100 employees, 68% said their AI agents had produced confident but wrong answers in the past six months. Respondents traced these to missing or inconsistent business context, not model error. That is a small survey of larger companies, so don't over-generalize it, but it matches what I see in the field: when an agent is wrong, the model is usually fine and the context it was handed is incomplete.
How KeewanoDB approaches it
KeewanoDB's design makes a few distinct choices worth separating from the marketing.
Entities as keys, events in sequence. Every event for a user, device, or agent hangs off that entity. Keewano's Lua scripting guide states that JOIN across tables does not exist in Keewano Lua, because everything needed is already in the per-user event stream. Instead of rows, you get per-user event arrays you iterate over.
An ingestion-time semantic layer. Context is attached when the event arrives, using LLMs. When an entity's status changes (for example active, then inactive, then flagged for fraud), every label stays in the sequence rather than being overwritten. This is the part I find most interesting, and also the part with the most risk, because an LLM labeling events at ingestion can mislabel them, and now the mislabel is baked into your history.
Agent access via SDK and MCP. Agents connect through an SDK and the Model Context Protocol. An acceleration engine lets agents run scripts inside the database through MCP, so the agent pushes computation to the data instead of pulling raw events out.
Built-in analytics agents. A separate layer includes a natural language query agent and an agent called Signal, which the company says runs anomaly detection and causal inference roughly once an hour.
Ingestion and interop. It supports Parquet and Apache Iceberg and can ingest event streams through systems such as Apache Kafka. Customers can send the same events to KeewanoDB and to a warehouse such as Snowflake, so you don't have to rip anything out to try it.
Per the launch coverage, it's a distributed, multi-sharded system running in Docker containers on Kubernetes, using vectorized instructions on standard CPUs rather than GPUs. It's a fully managed service on Google Cloud at launch, with other clouds and self-managed deployment planned for early 2027.
What's verified, what's a vendor claim
Most of the headline numbers come from the company, so separate them before you build a business case.
Confirmed by multiple reports: KeewanoDB reached general availability in mid-September 2026 alongside a $12 million seed round led by Hetz Ventures, with a16z speedrun, Remagine Ventures, DIG Ventures and angels participating. The founders previously built TestProject (acquired by Tricentis in 2019) and Devalore (acquired by Abra in 2022).
Vendor claims, not independently verified:
- Querying about 250 million events in under half a second. SiliconANGLE explicitly notes these figures have not been independently verified.
- The "no joins" architecture as a general advantage. It is the vendor's architectural description. I haven't found an independent technical review; the only technical detail I could find comes from the vendor's own documentation (the Lua guide).
- Customer-reported token savings versus warehouses. These come from the CEO via press coverage, with no published methodology.
Not known: price. The confirmed pricing model is per active entity, not per event, and the company says it's the only database of its kind with no per-event charge. I haven't found a publicly published price or tier, so check the current pricing page before assuming anything.
One more honest signal: analyst Philip Russom of IronSpark Analysis said he couldn't yet pigeonhole it, calling it a mashup of graph, neural net, time series, in-memory and real-time DBMS types, with native ML as the key differentiator. When an analyst can't categorize a product, plan a proof of concept, not a migration.
Where the pattern fits, and where it breaks
Event-per-entity storage is strong when your questions are about one entity's history, and weak when your questions span many entities. That tradeoff is the whole decision.
It fits well when:
- The agent's job is per-entity: "Why did this device fail?", "What did this customer do before churning?", "What has this agent already tried?"
- Order matters. Fraud, lifecycle, troubleshooting, and onboarding funnels all depend on sequence.
- You want the agent to see state transitions, not just the latest state.
It breaks down when:
- You need cross-entity analytics: revenue by region, cohort comparisons, anything that is naturally a
GROUP BYacross the whole population. A warehouse does this better, which is why the sensible path is to keep both and send events to each. - Your data is small and your questions are simple. A single well-indexed Postgres table with an
eventslog will beat a new database on operational cost. - Entity counts are huge but each entity has few events. Active-entity pricing could work against you, so model it once pricing is published.
The fact that Keewano supports sending the same events to both KeewanoDB and a warehouse tells you the vendor sees it as a complement, not always a replacement, though it says Keewano Cloud can run alongside a warehouse or replace one.
Get most of the benefit with tools you already run
You don't need a new database to adopt the underlying idea. The core move is: store an ordered, context-rich event log per entity, and give the agent that timeline instead of an aggregate. Here's a minimal version in Postgres.
CREATE TABLE entity_events (
entity_id TEXT NOT NULL,
seq BIGINT NOT NULL,
occurred_at TIMESTAMPTZ NOT NULL,
event_type TEXT NOT NULL,
context JSONB NOT NULL DEFAULT '{}',
PRIMARY KEY (entity_id, seq)
);
-- Everything for one entity, in order, no joins
SELECT seq, occurred_at, event_type, context
FROM entity_events
WHERE entity_id = 'acct_4821'
ORDER BY seq;
The composite key (entity_id, seq) keeps one entity's events physically close and ordered. Attach the context at write time, so the status change carries its reason:
import json
from datetime import datetime, timezone
def append_event(conn, entity_id, event_type, context):
with conn.cursor() as cur:
cur.execute(
"SELECT COALESCE(MAX(seq), 0) + 1 FROM entity_events WHERE entity_id = %s",
(entity_id,),
)
seq = cur.fetchone()[0]
cur.execute(
"""INSERT INTO entity_events
(entity_id, seq, occurred_at, event_type, context)
VALUES (%s, %s, %s, %s, %s)""",
(entity_id, seq, datetime.now(timezone.utc),
event_type, json.dumps(context)),
)
conn.commit()
append_event(conn, "acct_4821", "status_change",
{"from": "inactive", "to": "flagged",
"reason": "burst_activity_after_dormancy"})
Note the race: MAX(seq) + 1 is fine for low write volume per entity, but under concurrent writers you'll want a per-entity lock, an advisory lock, or a sequence strategy. Don't copy this into a high-throughput path unchanged.
Then give the agent a bounded timeline, not the whole table. Trim to the last N events plus a precomputed summary of older history, so you control token cost:
def timeline_for_agent(conn, entity_id, last_n=50):
with conn.cursor() as cur:
cur.execute(
"""SELECT seq, occurred_at, event_type, context
FROM entity_events
WHERE entity_id = %s
ORDER BY seq DESC LIMIT %s""",
(entity_id, last_n),
)
rows = list(reversed(cur.fetchall()))
return [
{"seq": s, "at": t.isoformat(), "type": e, "ctx": c}
for s, t, e, c in rows
]
This gets you the sequence-preserving behavior for the single-entity questions agents ask most. What it doesn't give you is the vendor's scale claims, the ingestion-time semantic layer, or the hourly anomaly agent. If you hit the limits of Postgres on event volume, that's when evaluating a purpose-built store makes sense.
A decision checklist before you adopt anything
Run these checks before moving agent memory to a new store, KeewanoDB or otherwise.
- Write down your top ten agent questions. If most are "what happened to this one thing," event-per-entity fits. If most are population-level, keep the warehouse as the source of truth.
- Test the semantic layer on your data. If an LLM labels events at ingestion, sample a few hundred and check the labels by hand. Mislabeled history is worse than missing history, because the agent trusts it.
- Benchmark on your workload. Treat any published speed claim as a starting hypothesis. Measure latency on your real event volume, with your real query shapes.
- Model the pricing unit. Active-entity pricing rewards long, dense event streams and punishes sparse, wide populations. Ask for current pricing and compute both cases.
- Check your exit path. Parquet and Iceberg support are good signs. Confirm you can export a full entity history in an open format before you commit.
- Plan for the deployment constraint. At launch it's managed on Google Cloud only, with other clouds and self-managed deployment planned for early 2027. If your data residency or cloud posture can't meet that, you may be waiting.
- Keep a dual-write period. Send events to both the new store and your existing warehouse, compare agent answers side by side, and cut over only when the new path is demonstrably better.
Choosing the right shape for your own agents
Event-per-entity storage is a real pattern for agent memory, and it's one of several retrieval shapes worth weighing when you design an agent backend. A hybrid setup is often a practical fit: a per-entity ordered event log for "what happened to this thing," plus search (keyword and vector) for unstructured context like documents and tickets, with the warehouse left alone for population-level analytics. The work is mostly in deciding what the agent should see for a given question and how much history fits in its context budget, not in picking a brand.
The unglamorous parts matter most: attaching context at ingestion, sampling labels for correctness, trimming timelines to control token cost, and keeping a fallback path when a new store misbehaves. Start from your actual agent questions and your real data volumes, and let those decide whether per-entity event storage, a hybrid setup, or just a better-shaped Postgres table is the right call.
Sources
- VentureBeat: Every user, device and agent gets its own table in KeewanoDB
- SiliconANGLE: Startup Keewano launches agent-focused database and pulls in $12M
- BigDATAwire: Keewano Raises $12M and Launches KeewanoDB
- CityBiz: Keewano Raises $12 Million
- Keewano Lua Guide
Work with BizFlowAI
If you'd rather have this built for you, that's what we do: production AI automation for solo founders and small teams — agents, integrations, and document pipelines that actually ship.
Request a free discovery call — 30 minutes, we map the highest-ROI automation in your workflow. No pitch deck, just engineering.
More guides like this on the BizFlowAI blog.
Frequently asked questions
What is event-per-entity storage and how does it differ from a data warehouse?
Event-per-entity storage makes each user, device, or agent a primary key and attaches every event for that entity in order, so the sequence is the native storage order. A typical warehouse stores rows or precomputed aggregates in tables and reconstructs history through timestamps and joins. Event-per-entity is strong for questions about one entity's history, such as what happened and in what order. It is awkward for cross-entity analytics like revenue by region, which a warehouse handles better.
Why do AI agents give confident but wrong answers?
The model is usually fine; the context it was handed is incomplete or inconsistent. Aggregates and snapshots discard the sequence of events that explains how an entity reached its current state, so the agent guesses at causality. In a July 2026 VentureBeat Pulse survey of 101 enterprises, 68% reported confident-but-wrong agent answers in six months, traced mostly to missing business context. Giving the agent an ordered event timeline instead of a flattened row reduces this failure mode.
What is KeewanoDB and what are its main claims?
KeewanoDB is a database that stores events per entity in sequence, uses no joins in queries, and attaches context at ingestion using LLMs. Agents connect through an SDK and the Model Context Protocol, and the company claims it can query about 250 million events in under half a second. That speed figure and the token-savings claims are vendor statements that have not been independently verified. It reached general availability in mid-September 2026 as a managed service on Google Cloud.
Can I use event-per-entity storage without adopting a new database?
Yes. The core idea is to keep an ordered, context-rich event log per entity and give the agent that timeline instead of an aggregate. A Postgres table with columns for entity_id, a sequence number, event type, timestamp, and payload, indexed on entity_id and sequence, gets most of the benefit. For small data and simple questions, this usually beats a new database on operational cost.
When should I not use event-per-entity storage for agent memory?
Avoid it when your questions span many entities, such as cohort comparisons or GROUP BY queries across the whole population, because warehouses do that better. It is also a poor fit when data is small and questions are simple, or when entity counts are huge but each entity has few events, since per-active-entity pricing could become costly. A sensible approach is to send the same events to both an event-per-entity store and a warehouse.