A human checking out on Amazon takes roughly twelve seconds to click buy now, confirm the address, and approve the charge. An autonomous agent buying that same item completes the entire flow in under half a second. This is not a small difference. It is a thirty-fold compression of the decision window, and it breaks every batch data architecture that powered the previous generation of payment systems.
If your agent is still reading spend limits, fraud signals, and merchant policies from a warehouse refreshed every hour, you are flying blind. The agent has already authorized a hundred transactions before the next batch even starts. This article shows why streaming databases are the only data layer that matches the latency budget of agentic payments, walks through a concrete per-agent spend aggregation in SQL, and explains the architectural shift you need to make.
How Agentic Payments Compare to Human Payments
To understand why batch fails, look at where the time goes in a payment decision.
A human checkout flow has a generous latency budget. The customer is reading the page, choosing a shipping option, and visually confirming the charge. The fraud system has hundreds of milliseconds (or even a full second) to score the transaction, and the data backing that score can be tens of seconds stale without any user noticing.
An agentic checkout flow looks completely different. The agent receives an instruction (book the cheapest direct flight to Tokyo under $1200), reasons about it, and executes a purchase. The whole sequence is non-interactive. There is no human waiting to click confirm. The latency budget is whatever the orchestrator allows before timing out the call.
Here is a typical breakdown for an agentic payment authorized through a protocol like AP2 or a custom agent gateway:
| Step | Typical latency | What happens |
| LLM reasoning + tool call | 200 to 400 ms | Agent decides to charge, picks merchant, picks amount |
| Risk and policy check | 50 to 100 ms | Spend limits, merchant allow-list, velocity rules |
| Payment network handshake | 50 to 150 ms | Authorization request, network response |
| Logging + receipt | 20 to 50 ms | Write the transaction to durable storage |
| Total budget | 400 to 700 ms | End-to-end agent decision |
The risk and policy step is where data freshness matters most. The agent is asking "has this user-agent pair already spent more than its budget today?" or "is this merchant on my allow-list right now?" If the answer is wrong by even one transaction, the system either blocks legitimate spend or lets a runaway agent burn through a budget cap.
This budget is non-negotiable. It is set by the LLM provider's latency, the payment network's SLA, and the user's expectation of an instant response. The data layer either fits inside the remaining 50 to 100 ms with fresh data, or it does not.
For a deeper view of how AI agents consume real-time data, see our piece on AI agents need real-time data.
Why Batch Architectures Can't Meet the Latency Budget
Batch architectures are everywhere in payments because they were good enough for the human-paced era. A nightly Spark job rolls up yesterday's transactions. An hourly Airflow DAG refreshes the velocity features. A 15-minute warehouse query updates merchant risk scores. These intervals worked when the slowest part of the system was a person.
In an agentic world, every one of these schedules is a window of broken consistency.
The freshness gap is structural, not configurable
You cannot fix batch latency by running the job more often. The floor is set by three structural costs:
- Scheduler overhead. Airflow, Argo, and similar systems take seconds just to dispatch a task. Running a DAG every minute is theoretically possible but operationally painful, and the tail latency on task pickup is unpredictable.
- Job startup. A Spark or Snowflake compute cluster takes 10 to 60 seconds to spin up an executor, attach storage, and start reading. Even on a warm cluster, the first I/O has to find the right file in object storage.
- Full or near-full table scans. Batch jobs read the source data, recompute the aggregate, and write it out. Even with partition pruning, you are reading minutes or hours of data per run.
The result is a hard floor of about 5 to 15 minutes between source events and serving freshness, with most production batch systems sitting at 30 to 60 minutes. That is roughly six orders of magnitude slower than the agent's decision budget.
What goes wrong inside the freshness gap
Here is what happens between batch refreshes when an agent is making decisions:
- Spend limit drift. The agent sees yesterday's total. It approves a $200 charge that would have crossed today's $500 cap. Multiply by 50,000 active agents and you have a finance incident.
- Stale fraud signals. An account was flagged compromised 20 minutes ago. The agent's risk lookup still returns "clean" because the feature pipeline has not finished its hourly run. The agent authorizes the fraud.
- Merchant policy lag. A merchant was suspended at 09:00 for chargebacks. The allow-list MV last refreshed at 08:30. Agents continue to route purchases through the suspended merchant until 09:30.
- Velocity windows that miss the spike. The whole point of a 5-minute velocity feature is to catch a burst. If the underlying aggregate is computed every 30 minutes, the feature is a slow-moving average, not a velocity signal.
These are not edge cases. They are the normal operating mode of any batch-fed agent system. We covered the broader pattern in agentic data architecture.
The compute-cost trap
Teams who try to push batch toward streaming usually end up running the same job every minute on a small slice of recent data. This works briefly, then becomes the most expensive line item in the data platform. You are paying for cluster startup, scheduler overhead, and storage reads at minute resolution, and you still have a 1 to 2 minute lag. There is no path from this configuration to a sub-second answer. The architecture is wrong.
The Streaming Database Alternative
A streaming database flips the model. Instead of recomputing aggregates on a schedule, it maintains them incrementally as each event arrives.
Here is the contrast in one diagram of the data path:
Batch path:
Event → Object storage → [wait 30 min] → Spark job → Reaggregate everything → Warehouse → Agent
Streaming database path:
Event → Streaming database → Incremental update of materialized view → Agent (~ms)
In the streaming model, the heavy work happens once per event, not once per query. When a new payment lands, RisingWave updates only the rows of the materialized view that depend on that payment (the agent's running total, the user's velocity counter, the merchant's hourly volume). When the agent reads the view, it is doing a primary-key lookup, not an aggregation.
This shift produces three properties that batch cannot match:
- End-to-end freshness in milliseconds. From event ingestion to view update is typically under one second on a warm cluster. The agent reads results that are at most a few hundred milliseconds behind reality.
- Constant-time reads. Materialized views are key-value lookups for the agent. Read latency is independent of how much history is in the system.
- Predictable cost per event. You pay to process each event once. There is no scheduler overhead, no cluster startup, and no scanning of historical data on every refresh.
This is why teams like Atome (a leading buy-now-pay-later platform in Southeast Asia) reduced their feature development cycle from weeks to a single day after replacing their Flink-and-Hive pipeline with RisingWave. Their fraud team can now ship a new agentic risk feature, validate it on live traffic, and roll it back if needed without ever waiting on a batch refresh. An anonymous global broker we worked with replaced their Flink + Kafka + Spark feature stack with RisingWave for fraud feature serving, collapsing three systems into one and eliminating the batch lag that had been blocking their automated trade authorization workflow.
For a broader comparison, see the best streaming database in 2026.
Streaming SQL Example: Per-Agent Spend Aggregation in 100ms vs 1hr
Let us make this concrete. Suppose you operate an agent payment platform. Each autonomous agent has a daily spend cap and a 5-minute velocity limit. Before approving any payment, the agent service needs to know the agent's running total for the day and its spend in the last 5 minutes.
In a batch architecture you would run this aggregate hourly. By the time it lands, an agent could have already burned through its cap. In a streaming database you maintain it as a materialized view that updates within milliseconds of every new payment.
Here is the full example, tested on RisingWave v2.8.0.
Step 1: Create the source table
CREATE TABLE aap17_agent_payments (
payment_id BIGINT PRIMARY KEY,
agent_id VARCHAR,
user_id VARCHAR,
amount DECIMAL,
payment_time TIMESTAMPTZ
);
In production this table would be backed by a Kafka topic or a CDC stream from your transaction database. RisingWave ingests from Kafka, Pulsar, Kinesis, and Postgres CDC without any extra connectors.
Step 2: Insert a baseline of 15 payments
INSERT INTO aap17_agent_payments VALUES
(1, 'agent_alpha', 'user_001', 12.50, NOW() - INTERVAL '12 minutes'),
(2, 'agent_alpha', 'user_002', 4.99, NOW() - INTERVAL '11 minutes'),
(3, 'agent_bravo', 'user_003', 38.00, NOW() - INTERVAL '10 minutes'),
(4, 'agent_alpha', 'user_004', 7.25, NOW() - INTERVAL '9 minutes'),
(5, 'agent_charlie', 'user_005', 19.99, NOW() - INTERVAL '8 minutes'),
(6, 'agent_bravo', 'user_006', 22.10, NOW() - INTERVAL '7 minutes'),
(7, 'agent_alpha', 'user_007', 3.49, NOW() - INTERVAL '6 minutes'),
(8, 'agent_charlie', 'user_008', 45.00, NOW() - INTERVAL '6 minutes'),
(9, 'agent_bravo', 'user_009', 14.30, NOW() - INTERVAL '5 minutes'),
(10, 'agent_delta', 'user_010', 9.99, NOW() - INTERVAL '4 minutes'),
(11, 'agent_alpha', 'user_011', 27.50, NOW() - INTERVAL '3 minutes'),
(12, 'agent_charlie', 'user_012', 6.75, NOW() - INTERVAL '3 minutes'),
(13, 'agent_delta', 'user_013', 11.20, NOW() - INTERVAL '2 minutes'),
(14, 'agent_bravo', 'user_014', 33.40, NOW() - INTERVAL '2 minutes'),
(15, 'agent_alpha', 'user_015', 5.99, NOW() - INTERVAL '1 minutes');
Step 3: Define the per-agent spend materialized view
CREATE MATERIALIZED VIEW aap17_per_agent_spend_mv AS
SELECT
agent_id,
COUNT(*) AS payment_count,
SUM(amount) AS total_spend,
ROUND(AVG(amount), 2) AS avg_payment
FROM aap17_agent_payments
GROUP BY agent_id;
This is the entire definition. RisingWave compiles it into a streaming dataflow that watches the source table and keeps the aggregates current. There is no scheduler, no DAG, no retry logic to write.
Step 4: Query the view
SELECT * FROM aap17_per_agent_spend_mv ORDER BY agent_id;
Output:
agent_id | payment_count | total_spend | avg_payment
---------------+---------------+-------------+-------------
agent_alpha | 6 | 61.72 | 10.29
agent_bravo | 4 | 107.80 | 26.95
agent_charlie | 3 | 71.74 | 23.91
agent_delta | 2 | 21.19 | 10.60
(4 rows)
The agent service can hit this view as a primary-key lookup on agent_id and get the current spend in well under 10 milliseconds.
Step 5: Insert 5 more "live" payments and re-query
To demonstrate that the view updates incrementally with no manual refresh, we insert five new rows representing payments that just happened.
INSERT INTO aap17_agent_payments VALUES
(16, 'agent_alpha', 'user_016', 18.75, NOW()),
(17, 'agent_bravo', 'user_017', 52.00, NOW()),
(18, 'agent_alpha', 'user_018', 9.50, NOW()),
(19, 'agent_delta', 'user_019', 41.30, NOW()),
(20, 'agent_charlie', 'user_020', 8.99, NOW());
SELECT * FROM aap17_per_agent_spend_mv ORDER BY agent_id;
Output:
agent_id | payment_count | total_spend | avg_payment
---------------+---------------+-------------+-------------
agent_alpha | 8 | 89.97 | 11.25
agent_bravo | 5 | 159.80 | 31.96
agent_charlie | 4 | 80.73 | 20.18
agent_delta | 3 | 62.49 | 20.83
(4 rows)
Notice that payment_count for agent_alpha went from 6 to 8 and total_spend jumped from 61.72 to 89.97 within seconds of the inserts. RisingWave did not rerun the whole aggregation. It applied the deltas to the existing state and pushed the new rows.
In a batch system, this update would have waited until the next hourly Spark run. The agent would have read the stale 61.72 number and potentially approved a payment that should have been blocked.
Step 6: Add a 5-minute velocity view
For burst protection you want a separate view that tracks spend in the last 5 minutes. This is a temporal filter on the same source.
CREATE MATERIALIZED VIEW aap17_recent_5min_spend_mv AS
SELECT
agent_id,
COUNT(*) AS recent_count,
SUM(amount) AS recent_spend
FROM aap17_agent_payments
WHERE payment_time > NOW() - INTERVAL '5 minutes'
GROUP BY agent_id;
SELECT * FROM aap17_recent_5min_spend_mv ORDER BY agent_id;
Output:
agent_id | recent_count | recent_spend
---------------+--------------+--------------
agent_alpha | 4 | 61.74
agent_bravo | 2 | 85.40
agent_charlie | 2 | 15.74
agent_delta | 3 | 62.49
(4 rows)
Two views, two different time horizons, both maintained by the same database, both fresh within seconds of each event. The agent service simply reads whichever view matches the policy it is enforcing. To learn more about temporal filters and how they slide forward as time passes, see the RisingWave docs on temporal filters.
Reference Architecture
Putting it together, here is what an agentic payment stack looks like with a streaming database as the operational data layer.
flowchart LR
A[Agent / LLM] -->|payment intent| B[Agent Gateway]
B -->|risk + policy lookup| C[(RisingWave<br/>Materialized Views)]
B -->|authorization| D[Payment Network]
D -->|webhook| E[Kafka topic<br/>payments]
F[Postgres<br/>users + agents] -->|CDC| C
G[Merchant policy DB] -->|CDC| C
E -->|stream| C
C -->|sub-second updates| B
C -->|long-term snapshots| H[(Apache Iceberg<br/>analytical lake)]
H --> I[Spark / Trino<br/>monthly reports]
The hot path (left side) is everything the agent reads inline during a decision: per-agent spend, velocity windows, merchant allow-lists, user risk scores. All of these are RisingWave materialized views fed by Kafka and CDC streams.
The cold path (right side) is everything humans and offline jobs read: monthly finance reports, regulatory audit exports, fraud-model training sets. RisingWave sinks to Apache Iceberg so the same source events become both the operational state for agents and the analytical history for the warehouse.
This is the split that matters: hot path is streaming, cold path is batch. They share data but never share the latency budget.
When Batch Still Has a Place
Batch is not dead. It is just no longer the default. There are workloads where its scheduling model and cost profile make it the right tool, and they have one thing in common: no agent decision waits on the result.
Specifically, batch is still appropriate for:
- Monthly settlement and reconciliation. Reconciling agent payments with the payment network's reports is a once-a-month process with no latency requirement.
- Regulatory and audit exports. PSD2, KYC trail exports, and chargeback reports are produced on a regulator's schedule, not an agent's.
- Fraud model training. Training a new model on six months of labeled fraud cases is a textbook batch workload. Run it in Spark on Iceberg, ship the model artifact, and serve features in streaming.
- Long-horizon BI. Quarterly trend analysis, executive dashboards aggregating year-over-year revenue, cohort analysis on payment behavior. These belong in Snowflake, BigQuery, or a Trino-on-Iceberg setup.
- One-time backfills. When you add a new feature, you often want to backfill history. RisingWave can handle this for moderate sizes, but for multi-year backfills a Spark job writing into Iceberg is usually cheaper.
The simple rule: if a human reads the result, batch is fine. If an agent reads the result inside a 500-millisecond decision, you need streaming.
FAQ
Why can't batch processing handle agentic payments?
Batch processing aggregates data on a schedule. Even an aggressive 15-minute schedule leaves a window during which agents make decisions on stale spend totals, stale fraud flags, and stale merchant policies. With 50,000 active agents executing several transactions per minute, that window produces real losses. Streaming databases close the window by maintaining results incrementally as each event arrives, with end-to-end freshness measured in milliseconds.
What latency budget do agentic payments require?
The total budget for an agentic payment is typically 400 to 700 milliseconds. The LLM consumes 200 to 400 ms, the payment network consumes 50 to 150 ms, and logging consumes another 20 to 50 ms. That leaves 50 to 100 ms for risk checks and policy enforcement. The data layer feeding those checks must respond in single-digit milliseconds with data that is at most a few seconds stale.
How does a streaming database differ from a batch ETL pipeline?
A streaming database such as RisingWave maintains query results incrementally as new events arrive. You write standard SQL once, and the database keeps the answer fresh by updating only the rows affected by each new event. A batch ETL pipeline recomputes the entire result set on a schedule by reading raw data from storage. The streaming approach delivers sub-second freshness with predictable cost per event. The batch approach is simpler for cold workloads but cannot meet agent latency budgets.
When is batch still appropriate in an agentic payment stack?
Batch is correct for any workload that does not block an agent decision: monthly settlement, regulatory exports, model training datasets, long-horizon analytics, and large historical backfills. The split is simple: anything an agent reads inline belongs in streaming; anything humans read after the fact belongs in batch.
Conclusion
Agentic payments collapse the human checkout window from twelve seconds to under one second. Every assumption your data platform made about freshness, query latency, and refresh cadence has to be revisited under that compression. Hourly batches that were perfectly adequate for human-paced commerce become a liability the moment an autonomous agent is making decisions against them. The losses are not theoretical. Spend caps drift, fraud flags arrive late, and suspended merchants stay reachable for the full length of the next batch cycle. Multiply by tens of thousands of concurrent agents and the gap turns into a steady leak of money and trust.
A streaming database is the operational data layer that fits inside the agent's latency budget. Per-agent spend, velocity windows, merchant policies, and fraud signals all live as materialized views that update within milliseconds of each event. Batch keeps its place for settlement, audit, and analytics, but it no longer sits on the hot path of a payment. The teams shipping agent-driven commerce in 2026 are the ones who have already drawn this line and built their hot path on streaming SQL.
Ready to move from batch to streaming for agentic payments? Try RisingWave Cloud free →
Join our Slack community to talk with the engineers building the streaming infrastructure for the agentic era.

