Blog · Experiment

Testing Agent Memory on microVMs

Let's demonstrate how Polign handles a cold start on Micro VMs.

September 4, 2026 · Anup Talwalkar · Polign

In my last post about agent memory, I wrote about how agents are moving to the edge, and how memory needs to move with them without picking up any side effects along the way. I wanted to take that a step further and show how Polign handles a cold start on micro VMs, and how it can be deployed at short notice.

A quick background on Polign, in case you are reading about it for the first time: Polign is a lightweight, stateless agent memory and vector database that keeps its durable state in object storage. With an S3-backed store, a write goes into the bucket's write-ahead log (WAL) before it is acknowledged. On a fresh server start, the Polign server reads the tail of the WAL along with the objects it needs from the bucket.

I ran a test on a small set of objects across six cold runs on AWS Lambda. This is the sequence I used:

  1. Write the preference in environment A.
  2. Read it from a fresh environment B.
  3. Have ten fresh readers query the same unchanged data in S3.
Environment A Writes the preference the original function is then deleted
Environment B Reads it back a new environment using the same S3 prefix
10 fresh environments Read concurrently each recovers the same record independently
same S3 prefix throughout
S3 Write log + collection schema No search segments or database snapshots were created in this test.
The Lambda environments share one S3 prefix. The writer finishes before any reader starts.

The setup for this exercise

  1. ARM64 Lambda custom runtime in us-west-1.
  2. 512 MiB of memory and an S3 bucket in the same region, with the segment cache capped at 64 MiB.
  3. Polign server zipped bundle (14.3 MiB).
  4. Invocation requests to Polign's local HTTP endpoint.
  5. Background persistor turned off, so the WAL entries are read directly instead of from segment objects.

Command to run

GOMEMLIMIT=384MiB ./polign-server \
  -store s3://YOUR-BUCKET/microvm-test \
  -persist=false \
  -maintain 0 \
  -http 127.0.0.1:23000 \
  -grpc 127.0.0.1:23001 \
  -hot-max 0 \
  -disk-cache-bytes 0 \
  -segment-cache-bytes 67108864 \
  -max-resident-searchers 64

The setup ensures that it's a cold start for the Polign server. The bucket still contained only the WAL and schema objects. The new process had recovered the record from the S3 log.

Polign relies heavily on S3's strong read-after-write consistency to find the logs. A fresh Polign node captures the highest visible log sequence in each partition and replays through those positions before accepting queries.

Tracing the timing profiles

The experiment ran over six cold starts to identify the initialization time and queries with warm invocations. All ten readers found the preference written earlier with environment A. Nothing was being written during the run, so this says nothing about write contention or readers keeping up with active ingestion.

Every result is for one stored record. This measures initialization and a small query on Lambda.

Run Result Notes
Cold initialization 645 ms p50
562 to 677 ms range
Six forced replacements; AWS Init Duration, including runtime and Polign startup.
Polign healthy 596 ms p50
527 to 630 ms range
Process start to /healthz returning 200, including startup WAL replay.
First query after replacement 23.0 ms p50
19.6 to 31.5 ms range
Six runs, querying the same record after startup replayed the retained S3 WAL.
Cold invocation, including init 669 ms p50
587 to 711 ms range
AWS billed duration for the same six cold invocations; excludes the caller's network round trip.
100 warm queries 23.7 ms p50
30.0 ms p95
43.4 ms p99
One invocation, sequential local HTTP requests. Minimum 19.9 ms; maximum 57.0 ms.
Memory 45.5 MiB p50 RSS
71 to 74 MB AWS peak
Runtime adapter and Polign together; six cold runs on a 512 MiB allocation.
10 concurrent cold readers 10/10 succeeded
22.2 ms query p50
30.4 ms max
Ten distinct runtime instance IDs; one existing record, no concurrent writes. Polign-ready p50 was 570 ms.

For this record, cold and warm query times are close. The time (645 ms) was spent initializing the runtime and replaying the WAL entries.

Two writers, one log

To test concurrent writes, I ran two writers against one shared WAL:

  • Each writer attempted 150 individual inserts of synthetic three-dimensional vectors and 15 writes to a shared record, with one request in flight at a time.
  • Both writers wrote to the same collection and S3 prefix.
  • A third Lambda function queried the collection throughout ingestion.

In a separate restart test, A's Polign process was killed while writer B continued writing. The HTTP 500 errors came from exhausting the WAL's conflict limits.

Run Successful writes Successful write latency
One writer, two rounds 330 / 330 22.0 ms p50
29.3 ms p95
146 ms max
Two writers, first pass
Three rounds
989 / 990
One HTTP 500 after 3.40 s
21.1 ms p50
28.7 ms p95
3,410 ms max
Two writers, repeat
Three rounds
989 / 990
One HTTP 500 after 3.29 s
21.2 ms p50
28.4 ms p95
2,717 ms max
Two writers, restart A during ingestion, two rounds 660 / 660 21.0 ms p50
27.0 ms p95
1,411 ms max

The goal of this exercise, and the encouraging result for me is that an agent's memory can outlive its process. In these tests, a replacement process recovered the acknowledged writes from S3. That makes Polign a promising fit for agents running in short-lived microVMs. Each session can conclude safely and be replaced without losing context.