Best practices

12 minute read

API Builder is a low-code / no-code developer application that you use to design and build a service using secure, modular, and reusable components. When used correctly, it can be a very powerful useful tool in your organization. Below are a list of some suggestions to help you get the most out of API Builder. For further reading on generic best practices for microservice development and deployment, be sure to check out the twelve-factor app methodology, which this guide has borrowed from. If you have any questions or feedback, you can use Axway’s support portal.

Codebase

  • Use version control.
  • For development, API Builder requires access to an npm repository (or registry.npmjs.org mirror). We do not recommend using offline archives of dependencies.
  • Keep your application small, and with single responsibility. Smaller applications are easier to develop, debug, manage and understand.
  • Keep your codebase clean and remove things that you are not using (e.g. log files, flows, API, endpoints, models, etc.).
  • We recommend that API Builder is developed on a local development machine. We do not recommend an “online” shared server approach to development where API Builder is installed on a machine that many developers access.

Dependencies

  • Understand semantic versioning.
  • Understand npm dependencies and dev dependencies and how to use them appropriately. By default, your API Builder application is configured to get the latest features and patches on npm install/update.
  • Uninstall dependencies that you are not using. These add to bloat, make your application bigger, and slower to install.
  • Use security tools such as npm audit to ensure your dependencies do not contain any vulnerabilities. API Builder uses WhiteSource (CVE monitoring), npm audit (CVE monitoring), AppSpider (web security), sonarqube (for code quality and security), and Fortify (for static code analysis).
  • Use package-lock or shrinkwrap when developing to ensure the same dependency tree. This will be created by default in up-to-date versions of npm.
  • If using package-lock then you should use the npm ci command instead of npm install in Docker or for faster installation.

Decide your architecture

Before you develop an API Builder service, you should consider your architecture. You can refer to our Performance Metrics Guide for some idea about capacity planning, but API Builder is fast, and will most likely be inhibited by other backend systems, such as your legacy API services or databases. You need to understand the performance of your backend systems and calculate how many requests you expect your API Builder service to handle. You must ensure that your backend systems are also scalable to handle the target workload.

For this reason, you need to decide which architecture is best suited for your constraints. For example, if you develop a REST API that communicates to backend systems and it returns in less than 2 seconds, then a RESTful architecture may be suitable. However, if your backend takes a long time (e.g. 10 seconds) to respond, that is a serious bottleneck. If your constraints are such that you cannot scale the backend system, then an Asynchronous architecture may be more suitable.

API Builder supports several architectures:

Configuring and securing your application

  • Separate config from code. Do not hard-code configuration parameters that will need to change in different environments, such as: hosts, URLs, credentials, timeouts, etc. Instead, manage configuration separately from your code. The easiest way is to use our Environmentalization guide. It is compatible with Docker.
  • Never hard-code credentials in the application. Use our Authentication Schemes to learn how to configure authentication, our Environmentalization guide to learn how to use environment parameters, and our Credentials guide for configuring credentials.
  • Never use a template (e.g. mustache, XSLT, doT) from an untrusted source. These can compromise your service’s integrity.
  • Do not disable API acessControl security.
  • Log at info level in production (for more information about logging modes, see Logging). Do not log sensitive information at info level. Note that by default in development mode, API Builder will log at debug level ( warning this includes sensitive information) for debug/development purposes. This is controlled via /conf/.env.

Design and develop

Each time you create a new API Builder project, and run “npm install”, you will pull the latest of our software, and the modules on which we depend. This ensures that you have all the latest features and security updates before you design your API Builder service. Your service should be a microservice, and kept as small as possible (see Microservice Design Ideals). During development, you will design your flows, and undoubtedly add flow-node plugins, or flow-trigger plugins.

During development, you should follow our Best Practices Guide, and Security Guide. It is important to develop a robust set of unit-tests (see ./tests for examples of how to write mocha tests) to ensure that your application is also compatible with the systems on which it depends, and those systems that also depend on it. This is key to the start of a healthy lifecycle as it enables you to confidently accept important updates and fixes.

At this stage, you will probably want to choose to lock down your dependencies (see package-lock and shrinkwrap). In short, package-lock describes the exact dependency tree that was generated, and subsequent installs are able to generate identical trees. You are unlikely to publish your project to an npm repository, and your project will most likely exist in a git repository and bundled for production (e.g. using Docker), so for those reasons, a package-lock would be adequate. You can check this file into git, and keep it up to date.

When developing your API Builder service, you should also build out a Continuous Integration (CI) to build and test your service. In CI, you should use “npm ci” instead of “npm install” as it will use the package-lock, and will be significantly faster.

During development, follow these general principles:

  • Decide on an API development strategy. API Builder supports API first with drag-and-drop flow-nodes (the recommended approach), model approach (connecting to a DB and generating a rich CRUD API from existing tables and views), or a custom API approach (write a pure JS API, but we would advise against this approach).
  • If using API first approach, employ Axway’s API first philosophy. This ensures that you design your API to suit the customer. API Builder supports Swagger 2.0 API definitions as the front-end API to your application. These can be used to define a rich customer-facing API documentation. Once defined, you can bind Flows to the existing Endpoints and use our drag-and-drop flow editor to implement your API.
  • From the UI, you can find many API Builder plugins on Plugins page. These extend the capabilities of API Builder. Be sure to check the available plugins for functionality before attempting to write your own implementation.
  • If you cannot find the capabilities you need on our Plugins page, you have a choice: use the JavaScript flow-node if it is a relatively simple fragment or if you need to produce a template, or use the API Builder SDK to write a custom flow-node that can be reused between your API Builder services.
  • We recommend that you connect to external services using Swagger 2.0 and OpenAPI 3.0 using our @axway/api-builder-plugin-fn-swagger flow-node.
  • When implementing your Flows, ensure all outputs are handled (e.g. Error).
  • We recommend that you implement your API to be as fast as possible. If API calls take too long, these can tie up resources and lead to unexpected timeouts.
  • Strive to make your application stateless as much as possible. This improves speed, scalability, and robustness.

Custom flow-node development

When writing code for the JavaScript flow-node, or writing a custom flow-node using our SDK, we recommend the following:

  • Learn JavaScript and Node.js. Note that JavaScript in web browsers has differences compared to Node.js which has a slightly different API.
  • Use Mozilla Developer Network (MDN) for your JavaScript reference as it is a complete/accurate resource.
  • Use the official Node.js documentation to see the features and behavior of the particular version of Node.js that you are using. Some parameters that you provide to API Builder may be configuring Node.js features.
  • Learn modern JavaScript ES6 (ECMAScript 6) and higher (there’s new features every year!) as this will save you time and make your code easier to maintain and super-charge your Flow development. Note that the supported features are down to the version of Node.js that you are using. Check node.green for ECMAScript feature support.
  • Do not mix tabs and spaces - this will drive people crazy. Your initial API Builder project’s files are all tab based. Pick one, and stick with it.
  • Use a linter to ensure code conformity and bug detection (we recommend eslint).
  • We recommend mocha for your unit-tests.
  • We recommend simple-mock to mock interfaces you do not need to test (e.g. fs) or that you wish to force errors.
  • We recommend nyc for calculating code coverage (we strive for 100% coverage).

Testing your application

  • Write unit-tests for all API endpoints and run them as part of your CI (in the ./tests directory, you will find examples of how to test the example Greet endpoint). We recommend mocha.
  • Learn how to debug a flow.
  • Use curl or postman for bespoke API requests (if you want, you can use postman for regression testing).

Tuning performance

  • Log at ERROR or INFO level only.
  • If you are not serving static files and you have a ./web directory, you can delete it to gain extra performance.
  • Disable Content-MD5 and ETag headers if your clients are not using them.
  • Use a memory model to cache responses from frequent and identical backend calls for things that will not change frequently (e.g. to query a list of Countries).
  • JSON encoding is expensive, so do not wrap large XML, Base64 or binary Buffer in JSON responses unless you have to.

Production

  • Log at ERROR or INFO level only.
  • Secured with TLS or SSL termination (depending on deployment architecture).
  • Use Docker to containerize your application.
  • Use security tools to scan your containers to ensure they do not have open ports or security vulnerabilities.
  • Use npm install with the --production flag.
  • Use kubernetes for scaling, and auto-healing.
  • We recommend you use Docker and not run as a stand-alone service (e.g. as opposed to running on a VM) so that it can be managed and scaled efficiently.
  • We recommend that you use API Central if you need to expose your service to the Internet.
  • Set NODE_ENV=production in the environment for security and performance.

Managing your service

  • The health of your Docker container is monitored via HEALTHCHECK and uses ./healthcheck.js to periodically ping the health check API /apibuilderPing.json
  • If flow-triggers become unhealthy (e.g. such as an inability to contact Kafka or Solace), your service will shut down as part of best practices for fault-tolerant microservice architecture so that it can self-heal and auto-restart. If you are not using Docker/Kubernetes in production, then you will need to employ a process manager (e.g. pm2).

Maintaining your service

API Builder is an Express application that provides a pluggable, drag-and-drop user interface with which to design complex flows. It is built with the help of many open source npm modules. But that software is not free. Axway invests in open source, and we do that by supporting the software that supports us. While we do not own many of the npm modules on which we depend, we regularly submit defects, help debug issues, and submit merge requests to these modules. In that way, npm is a healthy community where we support each other to make things better. Researchers regularly pour over these modules and sometimes find security issues. Before making them public, the owners of the modules have an opportunity to make a patch. When the patch is released, a public Common Vulnerabilities and Exposures (CVE) notice is created with the effected module(s) and version(s). We find and remediate these CVE regularly.

Every two weeks, API Builder releases new features, patches, and sometimes security fixes. In addition, because it is using other dependencies from npm, they too many have features, patches and security fixes. Before release, our software is rigorously regression tested, as well as run through WhiteSource (for CVE), npm audit (for CVE), AppSpider (for web security), sonarqube (for code quality and security), and Fortify (for static code analysis) so that you can have a high degree of confidence in our updates.

For these reasons, to maintain a healthy service, it is important to update your services regularly.

  • Use the latest, fully patched version of node that we support (see our Getting Started Guide and API Builder Node.js support policy for version restrictions).
  • Keep your dependencies up to date with their latest patches.
  • Every two weeks, Axway API Builder releases new features, patches, and security fixes. You should keep an eye on our Release Notes, our list of Deprecations, and our Updates. Keep abreast of the updates to ensure your application will be compatible with any change(s) that may be introduced. Occasionally, you may want to incorporate these security updates and fixes into your application.

Accessing your service

  • The health of your service can be monitored via the health check API /apibuilderPing.json
  • Links to all the API documentation for your service can be found at /apidocs.

API Discoverability

With API-first development, API Builder services can implement and expose multiple independent API documents on different URLs. These URLs are not always predictable. Starting with the Nantes release, API Builder services expose an API on the apidoc prefix (/apidoc) for discovering all API documents and their URLs.

This is an example of the API discoverability response format:

{
  // API discoverability response format version
  "version": "1.0",
  // Specification types
  "types": {
    // Array of individual OpenAPI documents
    "openapi": [
      {
        // document id
        "id": "dynamic",
        // document version [optional]
        "version": "1.0.0",
        // document name
        "name": "project",
        // document description
        "description": "An API Builder service",
        // document links.
        "links": [
          {
            // the URL of the document
            "url": "http://localhost:8080/apidoc/swagger.json",
            // the mime-type of the document [optional]
            "mimeType": "application/json",
            // the version of the specification used by this document (i.e. OpenAPI 2.0) [optional]
            "specificationVersion": "2.0"
          },
          {
            "url": "http://localhost:8080/apidoc/swagger.yaml",
            "mimeType": "text/yaml",
            "specificationVersion": "2.0"
          }
        ]
      }
    ]
  }
}
Last modified May 18, 2022: Nantes Release Notes (#83) (2311332)