Safeguard
Developer Tools•

Sequelize replacements or bind parameters: what is the difference?

Sequelize replacements are escaped and inserted into the SQL by the library, while bind parameters travel to the database separately from the query text.

Safeguard Security Team
4 min read

With replacements, Sequelize escapes your values and inserts them into the SQL string before sending it. With bind parameters, the values are sent to the database separately from the query text. Both avoid hand concatenation. Bind parameters keep values out of the SQL entirely, which is the stronger property.

What the documentation says

The Sequelize raw queries guide describes replacements as used in two ways, with named parameters starting with a colon or unnamed ones written as a question mark. It says the replacements are escaped and inserted into the query by Sequelize before the query is sent to the database. It then describes bind parameters as sent to the database outside the SQL query text.

The guide adds a rule you should remember: a query can have either bind parameters or replacements, not both.

FeatureReplacementsBind parameters
SyntaxColon name, or question markDollar number, or dollar name
Where the value goesEscaped and inserted into the SQL by SequelizeSent to the database outside the SQL text
Mixed in one queryNoNo
Who protects against bad inputThe library's escapingThe database's parameter handling

Why the difference matters

With replacements, the final SQL string contains your value. Protection depends on the library's escaping being correct for your dialect and settings. With bind parameters, the SQL text is fixed before any value arrives, so a value cannot change the structure of the statement.

Escaping is well tested in mature libraries, so replacements are not unsafe by design. But a long history of injection bugs comes from escaping assumptions that failed in a corner case. A design that never puts the value in the SQL text removes that class of problem.

Examples

// Replacements: the library builds the final SQL
await sequelize.query(
  'SELECT * FROM projects WHERE status = :status',
  { replacements: { status: 'active' }, type: QueryTypes.SELECT }
);

// Bind parameters: values are sent separately
await sequelize.query(
  'SELECT * FROM projects WHERE status = $status',
  { bind: { status: 'active' }, type: QueryTypes.SELECT }
);

The documentation says an exception is thrown if a replacement object has keys not found in the query, or the reverse, which helps catch typos.

What neither one fixes

Neither mechanism protects an identifier or a keyword. A column name in ORDER BY, or a table name, cannot be passed as a value. Use an allowlist in code for those.

const sortable = { created: 'created_at', name: 'name' };
const col = sortable[req.query.sort] ?? 'created_at';

The worst pattern is building the whole string with a template literal and passing it in with no parameters at all. A search for query calls that contain a template string with an interpolated variable will find most of them. Our post on ORM calls that bypass parameter binding lists patterns to search for in several libraries.

A rule for your team

  1. Prefer bind parameters for values.
  2. Allow replacements where the library or dialect makes bind awkward.
  3. Never concatenate request data into the SQL string.
  4. Use an allowlist for identifiers.
  5. Add a code search rule in CI for query calls with interpolated strings.

Safeguard scans dependencies, including Sequelize and database drivers, and policy gates can stop a pull request on a failed check. A free scan is at gold.safeguard.sh/scan.

Try it yourself

Run the code scan and open a query finding. Look for the difference between a value that is placed into the SQL string and one that is passed as a parameter.

Click through it at your own pace, or open it full screen.

Quick check

Can I use both in one query?

The Sequelize guide says a query can have either bind parameters or replacements.

Which is safer?

Bind parameters keep values out of the SQL text, so they remove the dependence on escaping.

Do they protect a column name in ORDER BY?

No. Map a fixed choice to a known identifier in code.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.