Database Integrations
Fluxify currently supports the following database integrations, allowing you to read and write data directly.
PostgreSQL
Connect to a PostgreSQL database to manage your application data.
Configuration
When setting up a PostgreSQL connection, you will need to provide:
- Host: The server address (e.g.,
db.example.comorlocalhost). - Port: The port number (default is
5432). - Database: The name of the specific database to connect to.
- Username: Your database user.
- Password: Your database password.
- SSL: Enable this if your provider requires a secure connection (common for cloud databases like Neon or Supabase).
- Query timeout: How long one query may run before it is stopped with an error. Default: 30 seconds. Raise it for slow reports; lower it to protect a busy database.
- Max connections: The most connections Fluxify keeps open to this database, per worker. Default: 10, at most 50. See How connections are handled before you change it.
Functionality
Once connected, you can use the following blocks to interact with your data:
- DB Get All: Fetch multiple rows.
- DB Get Single: Fetch one row.
- DB Insert/Bulk: Add one or many rows.
- DB Update: Modify existing data.
- DB Delete: Remove data.
- DB Transaction: Run multiple operations safely.
- DB Native: Run raw SQL queries for advanced use cases.
MySQL
Connect to a MySQL database. It takes the same settings as PostgreSQL (without SSL) and works with the same blocks.
Query timeout on MySQL
On MySQL the timeout stops reads that run too long. A write (insert, update, delete) is stopped when it waits too long for a row another request has locked.
MongoDB
Connect to a MongoDB database. Collections take the place of tables, and the same blocks read and write documents. Joins are skipped; to combine collections, use a DB Native block. Max connections defaults to 100, which is also the most you can set.
Transactions need a replica set
The DB Transaction block only works when MongoDB runs as a replica set (or behind a sharded cluster). A single standalone server still works for every other block. Test connection warns you when the server is standalone.
Ids
MongoDB ids (ObjectIds) come back as 24-character text, such as "65f1a2b3c4d5e6f708192a3b". You pass them back the same way, as text.
| You write | What happens |
|---|---|
A condition on id | It matches the document's _id. If the documents have their own id field, it matches that field instead, and the MongoDB id comes back as _id. |
A condition on a field that holds ids, such as riderId | The text matches the stored id. |
| An insert or update with id text in a field that holds ids | It is saved as a real id, the same type as the documents already there. |
Text that can't be an id (not 24 letters a–f and digits) on a field that holds ids | The block fails with an error that names the field, instead of quietly finding nothing. |
To make a new id, use ObjectId in a DB Native block: new ObjectId() makes a fresh one, and new ObjectId("65f1a2b3c4d5e6f708192a3b") turns text into an id. Return id.toHexString() to pass it on to other blocks as text. ObjectId exists only inside DB Native; everywhere else, ids are text.
Fluxify decides whether a field holds ids by looking at the collection's newest documents. On a new, empty collection, id text is saved as plain text, and an insert drops an id field, because nothing says yet that id is a field of its own.
Query timeout
Every database connection stops a query that runs longer than its Query timeout (30 seconds unless you change it). The block that ran the query fails with a timeout error, which you can handle like any other error. This keeps one slow query from holding a connection that other requests need.
How connections are handled
You don't need to open or close database connections yourself. Each database integration keeps a small set of open connections (a pool), and every route and workflow that uses that integration shares it. A request borrows a connection for each query and hands it straight back, so requests don't wait for a new connection to open.
You choose how many connections the pool may open with the integration's Max connections setting. If you leave it empty, the default applies. Each database also has a ceiling, so one integration can't make a worker hold more open connections than it can handle:
| Database | Default, per integration, per worker | Most you can set |
|---|---|---|
| PostgreSQL | 10 | 50 |
| MySQL | 10 | 50 |
| MongoDB | 100 | 100 |
When every connection is busy, the next query waits for one to free up instead of failing. On MongoDB that wait counts toward the Query timeout.
What to expect:
- The first request after a quiet period is slightly slower. It opens the pool. Every request after that reuses it.
- Idle pools close on their own. When nothing has used an integration for 7.5 minutes, its connections close and the next request opens them again. Your server admin can change this; see the idle timeout setting.
- Saving changes to an integration takes effect right away, including a new Max connections. New requests use the new settings at once. Requests already running finish on the old connections (for up to 30 seconds), which then close.
- A transaction keeps one connection for itself until it commits or rolls back. Keep transactions short so other requests aren't left waiting.
- Table details are remembered. The first query on a table looks up its primary key once, and later requests reuse what it found. If you change a table's primary key while Fluxify is running, the change is picked up the next time the pool opens: after it idles out, after you save the integration, or after a restart.
- Reads are prepared once. The first time a Get All, Get Single or Count block runs with a given set of active filters, its SQL is written and kept with the pool. Later runs with the same filters reuse it and only send their new values. A filter that is skipped, a value that is
null, or a list of another length counts as a different set, and is prepared once too. - Test connection uses its own short-lived connection, so testing never takes connections from running requests.
Plan your database's connection limit
Each worker keeps its own pool, so Max connections is per worker. The most connections your database will see from Fluxify is about workers × Max connections, for each integration. For example, 4 workers on a PostgreSQL integration set to 10 can open up to 40 connections, and scaling to 8 workers doubles that to 80.
Set Max connections so this total stays under your database's connection limit. Small hosted databases often allow only a few dozen connections, so lower it there. Raise it when a busy database has room and requests are waiting on each other.
Value types
Every DB block gives back the same kind of JavaScript value for a column, whichever database it came from:
| Column type | You get | Example |
|---|---|---|
Whole numbers (INT, BIGINT, MongoDB Long) | a number | 42 |
| Very large whole numbers (past 9007199254740991) | text, so no digit is lost | "9007199254740993" |
Decimals (NUMERIC, DECIMAL, MongoDB Decimal128) | text, so the value stays exact | "12.50" |
| Count | always a number | 3 |
Dates and times (TIMESTAMP, TIMESTAMPTZ, DATETIME, DATE, MongoDB dates) | a Date, in UTC | 2024-01-02T03:04:05.000Z |
| MongoDB ids (ObjectId) | text | "65f1a2b3c4d5e6f708192a3b" |
Doing math on decimals
A decimal is text, so row.price + 1 joins it ("12.501"). Turn it into a number first: Number(row.price) + 1. For money, where every cent must stay right, use a decimal library instead.
Why large numbers are text
JavaScript numbers can't hold every whole number past 9007199254740991 exactly, and a BigInt can't be sent in a JSON response. So those values come back as text.
A date becomes plain text (ISO format, in UTC) once it is sent in a response. Inside the flow it stays a Date, so you can pass it straight into another DB block's condition.
The MongoDB database handle in DB Native is the raw driver, so its results keep MongoDB's own types.
Custom conditions
The DB Get All, Get Single, Update and Delete blocks can use a Custom condition when the built-in operators (in, contains, between, is null, …) are not enough. What you write depends on the database:
| Database | You write | Example |
|---|---|---|
| PostgreSQL, MySQL | SQL, with run-time values in {{ }} | tags @> {{ input.tags }} |
| MongoDB | JavaScript returning a query filter object | return { tags: { $all: input.tags } } |
See Custom conditions for the details.
