API design: can I stop users from making queries that are extremely slow?

I'm building an API for a GeoDjango app, built on a Postgres database. I have a fairly newbie question.

My API is RESTful and read-only - it just allows users to query my data, with some filters, and get some results back.

My question is this. I know that there are some queries that it is possible to run through the API that will be extremely slow to execute (such as complex geographical queries over a large area - I do want to allow users to do this over a small area, though).

Is it possible that these queries might be so slow that they bring down the whole database? (I'm pretty sure I've seen this happen.) And if it is possible, what can I do about it?

Should I restrict the types of queries that are allowed through the API - e.g. check the input, and only execute queries over a small area?

Or (preferably, since it will be hard for me to predict exactly which queries will be slow) there a setting I can use on my database to kill these queries before they kill the whole application?

Answers


I don't think Django or geodjango offer any support for killing queries that take too long.

A quick search on the postgresql docs gave me the following: http://www.postgresql.org/docs/9.3/static/runtime-config-client.html#GUC-STATEMENT-TIMEOUT

statement_timeout (integer)

Abort any statement that takes more than the specified number of milliseconds, starting from the time the command arrives at the server from the client. If log_min_error_statement is set to ERROR or lower, the statement that timed out will also be logged. A value of zero (the default) turns this off.

Setting statement_timeout in postgresql.conf is not recommended because it would affect all sessions.

But this would affect all queries so you could break other functionality which takes longer for some reason.

The suggested way is to create a special user, e.g. web_user, on the database which runs these queries and limit the time for that user:

ALTER ROLE web_user SET statement_timeout = 10000;

In django, you can implement the statement_timeout (milliseconds) for a postgresql db in settings.py like this:

'default': {
    'ENGINE': 'django.db.backends.postgresql_psycopg2',
    'NAME': 'dbname',
    'USER': 'username',
    'PASSWORD': '',
    'HOST': '',
    'PORT': '',
    'OPTIONS': {
        'options': '-c statement_timeout=1000'
    }
},

Need Your Help

git command for making one branch like another

git github branching-and-merging

I'm trying to take a branch with changes and bring it back to be identical to the upstream it diverged from. The changes are both local and have been pushed to github, so neither git reset or git r...