Difference between filter and filter_by in SQLAlchemy
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
filter and filter_by both narrow query results in SQLAlchemy, but they are not interchangeable. The short version is that filter_by is a convenience API for simple equality checks, while filter accepts full SQL expression language and is the tool you reach for once the query gets even slightly complex.
What filter_by Does
filter_by takes keyword arguments whose names match mapped model attributes. Each keyword becomes an equality comparison, so it is concise and readable for straightforward lookups.
That reads naturally and is roughly equivalent to:
The convenience comes with a limitation: filter_by is mostly about attribute equals value comparisons. You do not use it for inequalities, LIKE, IN, OR, functions, or explicit SQL operators.
What filter Does
filter accepts SQLAlchemy expressions, which makes it far more flexible. You can compare columns, compose conditions, call SQL functions, and express range checks or joins directly.
Because filter works with column expressions, it is the better default once a query needs anything beyond plain equality.
Side-by-Side Examples
For a simple primary-table lookup, both methods are fine:
For a more realistic query, only filter stays comfortable:
Trying to express that with filter_by would either fail or become misleading because the API is not designed for operators such as greater-than or IS NULL.
Joins Make the Difference Clearer
The gap becomes even more obvious when another table is involved. Suppose User has a relationship to Address:
This is where filter shines. The condition names the exact model columns involved. With filter_by, you rely on keyword resolution against the current entity context, which can be surprising in joined queries and harder to read later. Many teams avoid filter_by once joins appear for that reason alone.
SQLAlchemy 2 Style
If you are using modern SQLAlchemy, you may prefer select(...).where(...) instead of the older Query API. The same conceptual difference still applies:
The API surface changes slightly, but the rule remains the same. filter_by is concise for simple mapped-attribute equality. Expression-based filtering is the broader and more explicit tool.
Readability Versus Power
There is nothing wrong with filter_by for very simple repository methods such as “find active users” or “look up order by external id.” It keeps code short and clear. The trouble starts when people try to stretch it beyond its sweet spot.
A practical guideline is:
- Use
filter_bywhen every condition is a direct equality on one mapped entity. - Use
filterwhen you need operators, functions,NULLchecks, joins, or explicit column references.
That rule keeps queries readable and makes later refactors easier.
Common Pitfalls
The most common mistake is trying to write non-equality conditions with filter_by, such as age greater than eighteen. That is what filter is for.
Another pitfall is assuming filter_by always targets the same model in a joined query. Depending on query construction, keyword names can resolve against the current entity context, which makes the code harder to reason about.
It is also easy to write User.is_active == True instead of User.is_active.is_(True) for nullable boolean columns. Both can work, but explicit is_ reads closer to SQL intent and avoids edge-case confusion.
Finally, remember that None comparisons are SQL comparisons, not normal Python identity checks. For null filtering, use User.deleted_at.is_(None) or is_not(None) rather than forcing it through filter_by.
Summary
- '
filter_byis a convenience API for simple equality checks on mapped attributes.' - '
filteraccepts full SQLAlchemy expressions and handles complex conditions cleanly.' - For joins, functions,
NULLchecks, and inequality operators, preferfilter. - '
filter_byis fine for short, obvious queries on a single entity.' - If a query starts feeling clever, switch to explicit column expressions before it becomes confusing.

