Flow reference: Storage & Databases

Take One Item

Pick one matching record and mark it in the same step, so two buyers never get the same item: stock delivery, codes, keys (Bottly storage or your PostgreSQL).

Pick one matching record and mark it in the same step, so two buyers never get the same item: stock delivery, codes, keys (Bottly storage or your PostgreSQL).

When and how to use it

Connect the input from the preceding step on the path that should perform this operation.
Fill the fields with data available in the trigger's context.
Connect the needed outputs; an unconnected path cannot run later blocks.

Configuration fields

Database — database


Bottly storage keeps records on Bottly (plan row limits, Storage page with import/export). Your PostgreSQL writes to your own database instead: the table and column names are used exactly as written, and values are sent as text parameters.

Input: Fixed choice.

Editor guidance: Bottly storage is built in (plan row limits apply). Your PostgreSQL uses your own database: tables and columns are used by name, values are sent as text parameters.

Available choices (preserve the exact value):
`` — Bottly storage
postgres — Your PostgreSQL


Connection string (Your PostgreSQL) — connection


A postgres://user:password@host:5432/database URL, kept in a bot env secret such as {env.DATABASE_URL} rather than typed into the block. The host must be reachable on the public internet; TLS is used unless the URL ends with ?sslmode=disable (?sslmode=verify-full also checks the certificate).

Input: Text with variable suggestions.

Editor guidance: Only used with Your PostgreSQL. Empty uses {env.DATABASE_URL}. Keep it in an env secret, never typed here. The host must be public; TLS is used unless the URL says sslmode=disable.

Format example, not a ready value for your server: {env.DATABASE_URL}.


Table — table


Name the bot-owned record collection consistently, such as tickets. A typo addresses a different table, not an alias of the old one.

Input: Text.

Format example, not a ready value for your server: stock.

Default: stock.


Filters (one per line) — filters


One condition per line: field = value, or != > < >= <= and contains (case-insensitive). Every line must match; leave it empty for all records. Values that are both numbers compare as numbers (10 > 9), anything else as text, and a missing field counts as empty, so sold != yes also matches records that were never marked. Values may use variables such as {user.id}.

Input: Multiline text.

Editor guidance: field = value per line; also != > < >= <= and contains.

Format example, not a ready value for your server: `sold != yes
product = {product}`.

Default: sold != yes.


Sort by field (empty = when saved) — sortField


Field to sort by: numbers by value first, then text, then records without the field. Leave it empty to sort by when the record was saved.

Input: Text.

Default: ``.


Order — sortOrder


desc puts the newest or highest first, asc the oldest or lowest. Find Many Records defaults to desc, Take One Item to asc (first in, first out).

Input: Fixed choice.

Default: asc.

Available choices (preserve the exact value):
asc — Oldest / lowest first
desc — Newest / highest first


Mark taken item (one field = value per line) — mark


Fields set on the taken record in the same step, one field = value per line (sold = yes, buyer = {user.id}). Pair them with a filter the mark makes false (sold != yes) so the record is never taken again.

Input: Multiline text.

Editor guidance: Set on the record as it is taken. Use a filter that the mark makes false (sold != yes + sold = yes) so it is never taken again.

Default: `sold = yes
buyer = {user.id}`.


Store as — storeAs


Choose a short result prefix such as result. Later blocks must use this same prefix and run after this block. It is not a Discord channel or a persistent table.

Input: Text.

Editor guidance: Read fields as {item.fieldName}

Default: item.

Outputs and next steps

taken: One record was taken and marked; its fields are in the Store as prefix.
empty: Nothing matched (or the storage could not be read; {prefix.error} says why); answer, for example, "Out of stock".

Read the result after this block, using its configured prefix and the fields supported by the selected operation. Do not assume every response has a text or id field.

Test and troubleshoot

Test a missing record, then save and read the same lookup value. Use a narrow filter for Update/Delete. Renaming a table or field changes where the lookup runs.

Save, validate and publish. Perform one real test and read the first relevant log error. [Testing](/docs/flow-testing) · [Variables](/docs/flow-variables) · [Permissions](/docs/flow-permissions).