API design

 

An API is a contract that describes the interaction between two or more systems, both from the perspective of external and internal use. It is the most efficient way to manage the complexity of the system being implemented, establish architectural boundaries, isolate data, and implement security requirements. Designing a good API involves several key stages, which I will discuss in this article.

Software development is generally data-driven. Most APIs are built around data sources (usually databases) and have a resource-oriented nature. There are exceptions in the form of APIs that manage system operations, which are typically well-standardized and reused across projects. These system-oriented APIs address tasks such as resource management and access control.

API from a State Perspective:

  • Stateful (server maintains state)
  • Stateless (no server-side state)

API Work Styles:

  1. Remote Procedure Call (RPC): One of the most widely used styles for building APIs. It is implemented through a client-server architecture pattern, allowing the client to execute its code remotely on the server. Usually, it uses compact binary formats. Examples include gRPC (https://grpc.io), and older examples like SOAP.

  2. Remote Method Invocation (RMI): A variant of RPC that "hides" the remote nature of the computation, making it appear as if the computations are performed locally on the client side.

  3. REpresentational State Transfer (REST): A set of principles for building lightweight APIs, typically using text-based formats for message exchange (e.g., JSON, XML). The textual message format allows for decoupling of server and client, without requiring shared libraries. It is widely used for web development.

  4. Specialized APIs: Typically built on a query language specifically designed for a server. Example: SQL.

General Overview

The most commonly used semantic versioning format is MAJOR.MINOR.PATCH-LABEL+MetaInfo:

  • MAJOR: Backward-incompatible changes
  • MINOR: Backward-compatible changes
  • PATCH: Localized fixes

APIs should consider compatibility:

  • Client version compatibility (supporting all clients of the previous API)
  • Server version compatibility (working on servers that support the previous API)
  • Protocol version compatibility (supporting all protocols of the previous API)

If any of these conditions are violated, the MAJOR version increases.

Versioning

  • Documentation
  • Expressiveness
  • Simplicity
  • Completeness
  • Version integrity
  • Predictability

Designing an API involves designing a standalone, logically complete "headless" application. This means an application that receives data as input and produces a result in a commonly used exchange format. API design is a process that can be structured as a standardized iterative process, consisting of the following key stages:

  1. Task description
  2. Requirements gathering
  3. Development of an architectural perspective
  4. Detailed implementation down to the code level

Key Considerations:

  • Naming (consistency, simplicity, brevity, etc.)
  • Data formats (intermediate states, serialization, edge cases, null values, primitive constraints)
  • Resource description (tables, relationships, views, diagrams, etc.)
  • Resource identification (unique keys, tuple-based identification, UUID)
  • Uniqueness (handling similarity issues)
  • Reproducibility
  • Security (generation based on real entropy)
  • Idempotence
  • Background processes
  • Scalability (partial use, pagination, data offsets, long-running queries)
  • Web-orientation (GET, POST, PUT, DELETE)

When developing an API, it is important to plan for horizontal scalability. This involves designing monitoring integration points during the early stages of the project (for automated management systems).

Common Monitoring Approaches:

  • Log-based monitoring: It's crucial to have end-to-end identification for all requests processed through the API chain.
  • Dedicated connection points with specific data formats: Data is retrieved on request.
  • Data exchange buses: A special message bus that handles monitoring time-series data, often implemented using MQ solutions.

Key Security Mechanisms:

  • Encryption
  • Authentication (confirming "I am who I say I am")
  • Authorization (defining "what I am allowed to do")
  • Resource usage quotas
  • Audit of actions

Authentication Methods:

  • Password
  • Bearer token (cookie, JWT, HTTP headers)
  • Certificate

Authorization Methods:

  • ACL (Access Control Lists)
  • Roles
  • Attributes (ABAC - Attribute-Based Access Control)

Comments

Popular posts from this blog

Books Every Developer Should Read (In My Opinion)

TypeScript: Why It's Needed and Why It's So Popular

Reactive Architecture at the Code Level