◉ANTIGRAVITY LABJP
Articles/Antigravity Basics
◉ Antigravity Basics/2026-06-12Intermediate

Measuring the Break-Even Point Between Google AI Pro and Ultra — 14 Days of Quota Data from Parallel Agent Runs

Is AI Ultra ($100/month, 5x the Pro limits) actually worth it? A Python harness that aggregates daily quota consumption from agent logs, 14 days of real measurements, and a formula that converts wait time into money to settle the question.

Google AI Pro4Google AI UltraAntigravity406quota10plan comparisoncost management5parallel agents3indie development27

✦ Premium Article

June's plan changes added a new option: AI Ultra at $100 per month, with roughly five times the usage limits of Pro.

As an indie developer who increasingly runs multiple Antigravity agents in parallel, I had a vague feeling of hitting the Pro ceiling toward the end of each month. But a vague feeling is a poor basis for an extra $80 a month. That money matters when you fund your own tools.

The exact quota numbers are not published anywhere. So the only way to know was to measure my own environment. I recorded fourteen days of consumption data before deciding anything.

This article documents the measurement harness, the numbers it produced, and the arithmetic that turns wait time into a break-even judgment.

The June 2026 Plan Lineup — What Is Public and What Is Not

First, the groundwork. As of June 2026, three options matter to individual developers.

  • AI Pro ($20/month): the standard plan, including Antigravity agent usage
  • AI Ultra ($100/month): the mid-tier added in June, with roughly 5x the Pro limits
  • Top-tier Ultra ($200/month): reduced from $250; limits are effectively a non-issue

Here is the catch: the "5x" multiplier is public, but the Pro baseline itself is not. Is it request count? Token volume? Are models weighted differently? Nobody outside Google knows. This opacity is precisely what forces plan decisions to run on gut feeling.

What is not published can still be observed from the outside. Agent execution history lives in local logs. That became my starting point.

Building a Small Measurement Harness

The first thing I built was a script that aggregates agent session logs by day.

One sentence on what problem this code solves: it records, in a consistent daily format, when I ran agents, at what parallelism, and at what moment I hit a rate limit.

Antigravity stores per-session execution history as JSONL files on the local machine. The location varies by setup, so the path is passed as an argument.

#!/usr/bin/env python3
"""agent_quota_tracker.py — daily aggregation of agent execution logs"""
import json
import sys
import re
from pathlib import Path
from collections import defaultdict
from datetime import datetime
 
# Patterns that indicate a rate limit (extend as you observe new ones)
RATE_LIMIT_PATTERNS = [
    re.compile(r"rate.?limit", re.IGNORECASE),
    re.compile(r"quota.+exceeded", re.IGNORECASE),
    re.compile(r"resource.?exhausted", re.IGNORECASE),
]
 
def is_rate_limited(text: str) -> bool:
    return any(p.search(text) for p in RATE_LIMIT_PATTERNS)
 
def collect(log_dir: Path) -> dict:
    daily = defaultdict(lambda: {
        "sessions": 0,
        "agent_runs": 0,
        "max_parallel": 0,
        "rate_limit_hits": [],
    })
    for jsonl in sorted(log_dir.rglob("*.jsonl")):
        active = []  # (start, end) pairs for estimating parallelism
        for line in jsonl.read_text(encoding="utf-8").splitlines():
            try:
                ev = json.loads(line)
            except json.JSONDecodeError:
                continue
            ts = ev.get("timestamp", "")
            day = ts[:10] if ts else "unknown"
            kind = ev.get("type", "")
            if kind == "session_start":
                daily[day]["sessions"] += 1
            elif kind == "agent_run":
                daily[day]["agent_runs"] += 1
                start = ev.get("started_at", ts)
                end = ev.get("ended_at", ts)
                active.append((start, end))
            elif kind == "error" and is_rate_limited(str(ev.get("message", ""))):
                daily[day]["rate_limit_hits"].append(ts[11:16])
        # Treat the max number of overlapping runs as the day's parallelism
        for day, stats in daily.items():
            overlaps = [
                sum(1 for s2, e2 in active if s2 <= s1 < e2)
                for s1, _ in active
            ]
            if overlaps:
                stats["max_parallel"] = max(stats["max_parallel"], max(overlaps))
    return daily
 
def main():
    if len(sys.argv) < 2:
        print("usage: agent_quota_tracker.py <log_dir>")
        sys.exit(1)
    daily = collect(Path(sys.argv[1]))
    for day in sorted(daily):
        s = daily[day]
        hits = ",".join(s["rate_limit_hits"]) or "-"
        print(f"{day}  runs={s['agent_runs']:3d}  "
              f"parallel_max={s['max_parallel']}  limited_at={hits}")
 
if __name__ == "__main__":
    main()

Two design decisions are worth explaining.

First, rate-limit detection works by pattern-matching error messages. Since the internal quota mechanics are invisible, the moment you hit the wall is the only fact observable from the outside. I built around that fact.

Second, parallelism is estimated from overlapping execution windows rather than counted directly. As you will see below, consumption pace correlated more strongly with parallelism than with raw run count.

Register the script with cron or Antigravity 2.0's scheduled execution, run it nightly, and the record accumulates on its own.

✦

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
✦A complete Python script (~60 lines) that aggregates daily quota consumption from agent execution logs
✦Raw data from 14 days of measurement showing how parallelism correlates with rate-limit hits — and how to read it
✦A break-even formula that converts wait time into money, plus decision criteria for three usage patterns
Secure payment via Stripe · Cancel anytime
✦

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Antigravity Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • ✦Copy-paste ready implementation code
  • ✦New advanced guides published daily
  • ✦$5/mo or $10 for lifetime access
View Membership →

Related Articles

◉ Antigravity2026-10-28
When Antigravity Says Failed to Fetch: Decide the First Three Places to Look
A short triage order for Failed to Fetch in Antigravity: check whether the destination is reachable, whether you are still signed in, and whether a proxy or VPN sits in the middle. Includes copy-paste terminal checks and what each result means.
◉ Antigravity2026-10-16
When Antigravity Says the Server Crashed Unexpectedly: Check the CPU, WSL, or Version First?
The editor opens but the agent dies right away with 'server crashed unexpectedly'. A short triage across three suspects, CPU AES support, WSL or SSH paths, and the app version, built from public forum and issue reports, with the unconfirmed parts marked as unconfirmed.
◉ Antigravity2026-10-15
Before You Press Delete on an Antigravity Project, Can You Name Three Things That Stay?
Does deleting a project in Antigravity 2.0 remove your source code? A community explanation, split into its two storage locations, plus a read-only script and a safe order for freeing disk space.