Building RESTful Web APIs with Dart, Aqueduct, and PostgreSQL — Part 1

graphicbeacon profile image Jermaine Oppong Updated on ・5 min read

Featured image for Building RESTful Web APIs with Dart, Aqueduct and PostgreSQL

PLEASE NOTE: As of Dart 2 the API for Aqueduct has changed, leading to breaking changes. This article was based on Aqueduct 2.5.0 for Dart v1.

I have updated this as a new video series: http://bit.ly/aqueduct-tutorial

In this new series on yet another RESTful API tutorial (#yetanotherrat), we will be exploring the Dart platform and its offering when it comes to building server-side applications.

Following on from my last post exploring the Dart language, I’d also been investigating how one might go about building RESTful services with Dart. Some further digging and I stumbled across Aqueduct by Stable Kernel. I was impressed at first glance seeing that it has already passed version 2 and once I figured the documentation was comprehensive with easy-to-follow examples, I was convinced to explore further.

Upon the experience of such a productive and refreshing time going through its documentation and following their example, I am now pleased to be taking you on this journey with me to build a working api from start to finish!

Prefer a video? Watch on Youtube

So what's Aqueduct?

Well it’s an open-source framework for creating and deploying RESTful web apis on the server. It has a similar flavour to Express and Hapi, even .NET Web API, offering a point of entry with a comprehensive list of features.

My favourite ones are:

  1. Fluid, chainable routing. A functional style to composing your routes and its handler methods
  2. A CLI tool. This allows you to scaffold your next project by issuing commands
  3. Multi-threading out of the box. Spins up multiple instances of your application via Dart's "isolates", scaling across all CPU cores on the server.
  4. Has an inbuilt ORM. A must-have if you work with relational databases! Also supports databse migration.
  5. Has an integrated testing library. Because you need to test all the things! Plays well with tools like TravisCI.

In the series we will be building an api for a personal reading list (let’s call it FaveReads 📚), covering these topics:

Shall we begin?

Setting up and running the example

If you haven’t already, I’d encourage you to install the Dart SDK. It’s got instructions for Windows, Mac and Linux.

You can confirm you have Dart running by checking the terminal:

dart --version

Dart comes with a tool called pub to manage its packages. Let’s use this tool to install Aqueduct:

pub global activate aqueduct

This gives us access to the aqueduct executable. Change to your working directory and let us create our project:

aqueduct create fave_reads && cd fave_reads

You should now be in the fave_reads directory with all the project files. For now we'll focus on:

  • bin/main.dart creates our server and starts the app
  • lib/fave_reads_sink.dart sets up your application with its configuration
  • pubspec.yaml contains metadata about the project. Similar to having a package.json for Node.js development

Let’s start the application using either commands below:

aqueduct serve # or `dart bin/main.dart`

And here we go:

Aqueduct serve terminal

We now have a server running at http://localhost:8081 with /example being the only created route. Accessing http://localhost:8081/example will return the response below:

{ "key": "value" }

At this point its worth mentioning that Aqueduct has the concept of a RequestSink, which according to the documentation:

handles the initialization of an application, including setting up routes, authorization and database connections.

An application needs one RequestSink subclass to enable it to receive requests. Our example has a FaveReadsSink extending the base RequestSink class to enable us to override its methods with our own implementation. These are setupRouter and willOpen. The first method will allow us to define our routes with associated controllers and other middleware, while the latter allows us to perform any asynchronous initialisation after the routes are set up and before the application can receive requests.

The default response type is set to JSON for current requests. However this can be set to whatever content type is appropriate to meet our needs.

Let’s demonstrate this by creating a second route in setupRouter method:

router.route('/').listen((request) async {
  return new Response.ok('Hello world')
    ..contentType = ContentType.TEXT;

Using method cascades, we are able to set the contentType property to text/plain. The ContentType utility comes inbuilt with Dart and can be used through the style below:

new ContentType(primaryType, subType, {String charset, Map parameters});

It’s already got constants for HTML, JSON and TEXT so in most scenarios you should just use those.

Now restart the server by killing the current process and running aqueduct serve again. Accessing the root path should now give you this:

Aqueduct server localhost

Before we wrap up, lets scale up our application instances to the number of cores we have. In bin/main.dart it is currently set to 2 when app.start is invoked:

await app.start(numberOfInstances: 2);

To resolve this, we will import Dart’s Platform class from the “dart:io” library and amend main.dart as follows:

import 'dart:io' show Platform;

Future main() async {
  await app.start(numberOfInstances: Platform.numberOfProcessors);

Some development tips for VS Code 👈

Firstly, make sure to install the Dart extension by Dart Code, to enable Dart and Flutter support.

Secondly, add a launch configuration for Dart with this setting:

  "name": "Dart",
  "type": "dart",
  "request": "launch",
  "program": "${workspaceFolder}/bin/main.dart"

This will allow you to run the app through VS Code with the ability to add breakpoints to help with debugging.

VS Code debugging with Dart

Before we wrap up, I want to ask you something…What do you expect to gain at the end of this series? Add a comment below to let me know, thanks.

And this concludes Part 1 of the series. The code for this series is available on github and will be updated as we go through the series. Stay tuned for more.

Further reading

  1. Aqueduct documentation
  2. Getting started with Pub
  3. Presentation by Joe Conway at Dart Developer Summit 2016

Originally posted on Medium

Posted on by:

graphicbeacon profile

Jermaine Oppong


Web Developer | Google Dart enthusiast | Egghead.io instructor | YouTuber 📹 | Read my blog ✍🏾 https://www.creativebracket.com


markdown guide

August 12, 2018

As of Dart 2: I want to clarify things that needs to be changed.

router.route('/').listen((request) async {
  return new Response.ok('Hello world')
    ..contentType = ContentType.TEXT;


    router.route('/').linkFunction((router) async {
      return Response.ok("Hello World");

Although I would like to point out many things, it's better to check out in their documentation because a lot of it are deprecated.

Have a great day!


Thanks Vince. Will do the rounds and make the edits soon.


HI jermaine,

I had problem running "pub global activate aqueduct" i get this error

"%1 is not a valid Win32 application.

Command: C:\Program Files\Dart\dart-sdk\lib_internal\pub\asset\7zip\7za.exe e data.tar.gz

can you help resolve this error


Hi @faridak ,

Thanks for going through this tutorial series. I did some digging around and it appears to be a Windows related issue, caused when having spaces in your path, so "Program Files".

You can follow the recommended solution via that link, or even better install Dart through the Chocolatey package manager for Windows. It should be placed on a path without spaces.

Try and let me know how that turns out.


Hi Jermaine,

I did the install using Chocolatey, and this error remains.. I know it is a windows relates that the path is not defined .. but hot to set the Path so it can work... i am stuck in the installation.

Will appreciate if you can help, otherwise thank you.. .it frustrates me ..

The path is defined, its just that the Program Files folder has got spaces in it. It may be that the previous install of Dart is taking precedence over the Chocolatey install.

Can you confirm that running where dart in the command prompt is showing C:\tools\dart-sdk\bin\dart.exe? If its not happening then try these steps:

  1. Uninstall the earlier install of Dart, the one in C:\Program Files...
  2. Try adding C:\tools\dart-sdk\bin to your Path in Environment Variables.
  3. Run where dart to confirm the correct path is showing

Or you could just remove all installs of Dart, including Chocolatey's one and reinstall using Chocolatey. Should fix the path 🤞


Hi Jermain, nice article.

Dart is very very easy to set up :-) I'll be following along hoping to get some familiarity before checking out Flutter!


Hey Rhymes,

Thanks for the feedback. I'm very pleased that you found Dart easy to set up, since first impressions really count. Part 2 will be out this week and I intend on keeping myself accountable.


Nice article, I hope by the end of your series, I will understand RESTful Web APIs.


Hey Rameses, thanks for the feedback. This article assumes you have a general understanding of RESTful Web APIs. However, I hope you see how they can be applied in a real world scenario via the Dart platform.


I can't unable to create project using aqueduct create cmd, pls guide me how can I install on Windows.


Hi Arun, please see the updated video series on get started bit.ly/aqueduct-tutorial

Install Aqueduct on Windows by running pub global add aqueduct, assuming you've installed Dart already. See this lesson for details on installing Dart for Windows.