Skip to content

Find one chunk, read its neighbours

Search narrow, then widen with the keys you already have.

Why

Retrieval wants two things that pull against each other. It wants small chunks, because a small chunk embeds precisely and a large one blurs into an average of everything it contains. And it wants enough surrounding text for the answer to make sense. Chunk small and search results are fragments; chunk large and the search gets vague.

You do not have to choose. Chunk small so the search is sharp, then use the keys you got back to read the neighbours. The sort key already encodes chunk order, so a BETWEEN either side of the hit is a single Query on one partition. The search never carried that text and never paid for it.

Grouping the index by corpus rather than by document is the decision that makes this work at all. Group by document and the SearchSchema's HASH forces you to name a document before you can search, which is the question you were trying to answer.

Projection matters more here than it does on a GSI. Search results are capped at TopK but they are not capped in size, and vector work is billed by bytes. Returning a full chunk body for every hit means paying for text you mostly discard, on every single query. Ask for the keys, then fetch the handful of bodies you actually need.

One convenience worth knowing: the vector attribute is left out of results unless a ProjectionExpression explicitly asks for it and the index projects it. You almost never want a 384-number array in a result payload, and the default is the one you want.

Chunk small for a sharp search, project only the keys, then expand through the sort key and fetch bodies by key: two cheap reads beat one fat one.

Try it. Then change it.

Predict what each request will do. Run it, inspect the response, then change a value in the workbench and try again.

  1. "How do I rotate an API key safely." A ProjectionExpression brings back only the keys, so each result is tiny. The answer is which chunk, not the chunk itself.

  2. The winning chunk was CHUNK#0003 of the authentication document. A sort-key BETWEEN either side of it pulls the surrounding context in one cheap Query. The search never had to carry any of this.

  3. The other half of the pattern: take the keys the search returned and fetch their full items by key, in one round trip. Two cheap operations instead of one fat one.

Built on this

DocChunksDynamoDB workbench
Ready to run
Explore an access patternSelect to load & run

"How do I rotate an API key safely." A ProjectionExpression brings back only the keys, so each result is tiny. The answer is which chunk, not the chunk itself.

Request
Execute against the local Dynoxide engine
ReturnedFiltered outChanged
pk(pk)
sk(sk)
corpus
text
embedding
DOC#authentication
CHUNK#0001S
api-docsS
API keys authenticate a machine, not a person, and carry the permissions of the project they belong toS
[-0.0903, 0.0768, -0.0248, … 384]L
DOC#authentication
CHUNK#0002S
api-docsS
Create a key from the project settings page and copy it immediately; the value is never shown againS
[-0.0184, 0.0255, -0.1061, … 384]L
DOC#authentication
CHUNK#0003S
api-docsS
To rotate a key, create the replacement first, deploy it, then revoke the old oneS
[-0.0254, 0.0232, -0.0294, … 384]L
DOC#authentication
CHUNK#0004S
api-docsS
Revoking a key takes effect within a few seconds across every regionS
[0.0775, 0.0311, 0.0489, … 384]L
DOC#authentication
CHUNK#0005S
api-docsS
Keys that have not been used for ninety days are flagged in the dashboardS
[-0.0047, 0.0562, -0.0394, … 384]L
DOC#rate-limits
CHUNK#0001S
api-docsS
Every endpoint is rate limited per project rather than per keyS
[0.0857, -0.05, -0.0249, … 384]L
DOC#rate-limits
CHUNK#0002S
api-docsS
A limited request returns 429 with a Retry-After header in whole secondsS
[-0.0397, 0.0585, 0.0368, … 384]L
DOC#rate-limits
CHUNK#0003S
api-docsS
Back off exponentially with jitter rather than retrying on a fixed intervalS
[-0.0835, 0.0228, 0.03, … 384]L
DOC#rate-limits
CHUNK#0004S
api-docsS
Bulk endpoints have their own separate budget and do not consume the general oneS
[0.0401, 0.0003, -0.0461, … 384]L
DOC#webhooks
CHUNK#0001S
api-docsS
Webhooks deliver at least once, so your handler has to be idempotentS
[-0.0533, 0.0154, -0.007, … 384]L
DOC#webhooks
CHUNK#0002S
api-docsS
Each delivery is signed; verify the signature before you trust the bodyS
[-0.0299, 0.0454, 0.0259, … 384]L
DOC#webhooks
CHUNK#0003S
api-docsS
Failed deliveries are retried for twenty-four hours with widening gapsS
[-0.0031, 0.0005, 0.1251, … 384]L
DOC#webhooks
CHUNK#0004S
api-docsS
Respond within five seconds; do the slow work after you have acknowledgedS
[-0.0274, 0.0033, 0.0571, … 384]L
DOC#webhooks
CHUNK#0005S
api-docsS
Replay a delivery from the dashboard when a handler was broken at the timeS
[-0.0352, -0.0425, 0.0257, … 384]L
Awaiting request
Your next query starts here.

Choose an access pattern above, or build your own request. See what comes back and what it costs.

Powered by DynoxideWASMStarts on your first run · Runs locally in your browser