#performance #http #ansible #jmeter

app drill

Drill is a HTTP load testing application written in Rust inspired by Ansible syntax

13 unstable releases (5 breaking)

0.7.1 Nov 27, 2020
0.6.0 Apr 26, 2020
0.5.0 Mar 20, 2019
0.4.1 Nov 18, 2018
0.1.0 Jun 14, 2017

#4 in Profiling

Download history 28/week @ 2020-10-02 20/week @ 2020-10-09 18/week @ 2020-10-16 25/week @ 2020-10-23 3/week @ 2020-10-30 19/week @ 2020-11-06 19/week @ 2020-11-13 33/week @ 2020-11-20 66/week @ 2020-11-27 32/week @ 2020-12-04 43/week @ 2020-12-11 17/week @ 2020-12-18 12/week @ 2020-12-25 15/week @ 2021-01-01 31/week @ 2021-01-08 15/week @ 2021-01-15

127 downloads per month

GPL-3.0 license



Drill is a HTTP load testing application written in Rust. The main goal for this project is to build a really lightweight tool as alternative to other that require JVM and other stuff.

You can write benchmark files, in YAML format, describing all the stuff you want to test.

It was inspired by Ansible syntax because it is really easy to use and extend.

Here is an example for benchmark.yml:


concurrency: 4
base: 'http://localhost:9000'
iterations: 5
rampup: 2

  - name: Include comments
    include: comments.yml

  - name: Fetch users
      url: /api/users.json

  - name: Fetch organizations
      url: /api/organizations

  - name: Fetch account
      url: /api/account
    assign: foo

  - name: Fetch manager user
      url: /api/users/{{ foo.body.manager_id }}

  - name: Assign values
      key: bar
      value: "2"

  - name: Fetch user from assign
      url: /api/users/{{ bar }}

  - name: Fetch some users
      url: /api/users/{{ item }}
      - 70
      - 73
      - 75

  - name: Fetch some users by hash
      url: /api/users/{{ item.id }}
      - { id: 70 }
      - { id: 73 }
      - { id: 75 }

  - name: Fetch some users from CSV
      url: /api/users/contacts/{{ item.id }}
    with_items_from_csv: ./fixtures/users.csv
    shuffle: true

  - name: POST some crafted JSONs stored in CSV
      url: /api/transactions
      method: POST
      body: '{{ item.txn }}'
        Content-Type: 'application/json'
      file_name: ./fixtures/transactions.csv
      quote_char: "\'"

  - name: Fetch no relative url
      url: http://localhost:9000/api/users.json

  - name: Interpolate environment variables
      url: http://localhost:9000/api/{{ EDITOR }}

  - name: Support for POST method
      url: /api/users
      method: POST
      body: foo=bar&arg={{ bar }}

  - name: Login user
      url: /login?user=example&password=3x4mpl3

  - name: Fetch counter
      url: /counter
    assign: memory

  - name: Fetch counter
      url: /counter
    assign: memory

  - name: Fetch endpoint
      url: /?counter={{ memory.body.counter }}

  - name: Reset counter
      method: DELETE
      url: /

  - name: Custom headers
      url: /admin
        Authorization: Basic aHR0cHdhdGNoOmY=
        X-Foo: Bar
        X-Bar: Bar {{ memory.headers.token }}

As you can see, you can play with interpolations in different ways. This will let you specify a benchmark with different requests and dependencies between them.

If you want to know more about the benchmark file syntax, read this


The easiest way right now is to install with cargo:

cargo install drill
drill --benchmark benchmark.yml --stats

or download the source code and compile it:

git clone git@github.com:fcsonline/drill.git && cd drill
cargo build --release
./target/release/drill --benchmark benchmark.yml --stats

Note: You will need to install libssl-dev and pkg-config packages.




This is the list of all features supported by the current version of drill:

  • Concurrency: run your benchmarks choosing the number of concurrent iterations.
  • Multi iterations: specify the number of iterations you want to run the benchmark.
  • Ramp-up: specify the amount of time it will take drill to start all iterations.
  • Delay: introduce controlled delay between requests. Example: assigns.yml
  • Dynamic urls: execute requests with dynamic interpolations in the url, like /api/users/{{ item }}
  • Dynamic headers: execute requests with dynamic headers. Example: headers.yml
  • Interpolate environment variables: set environment variables, like /api/users/{{ EDITOR }}
  • Request dependencies: create dependencies between requests with assign and url interpolations.
  • Split files: organize your benchmarks in multiple files and include them.
  • CSV support: read CSV files and build N requests fill dynamic interpolations with CSV data.
  • HTTP methods: build request with different http methods like GET, POST, PUT, PATCH, HEAD or DELETE.
  • Cookie support: create benchmarks with sessions because cookies are propagates between requests.
  • Stats: get nice statistics about all the requests. Example: cookies.yml
  • Thresholds: compare the current benchmark performance against a stored one session and fail if a threshold is exceeded.

Test it

Go to the example directory and you'll find a README how to test it in a safe environment.

Disclaimer: We really recommend not to run intensive benchmarks against production environments.

Command line interface

Full list of cli options, which is available under drill --help

drill 0.7.1
HTTP load testing application written in Rust inspired by Ansible syntax

    drill [OPTIONS] --benchmark <benchmark>

    -h, --help       Prints help information
        --no-check-certificate    Disables SSL certification check. (Not recommended)
        --relaxed-interpolations    Do not panic if an interpolation is not present. (Not recommended)
    -s, --stats      Shows request statistics
    -q, --quiet      Skips output of individual request statistics
    -n, --nanosec    Shows statistics in nanoseconds
    -V, --version    Prints version information

    -b, --benchmark <benchmark>    Sets the benchmark file
    -c, --compare <compare>        Sets a compare file
    -r, --report <report>          Sets a report file
    -t, --threshold <threshold>    Sets a threshold value in ms amongst the compared file


  • Complete and improve the interpolation engine
  • Add writing to a file support


This project started as a side project to learn Rust, so I'm sure that is full of mistakes and areas to be improve. If you think you can tweak the code to make it better, I'll really appreciate a pull request. ;)


~299K SLoC