Commerce APIs - Aren't They All the Same?
Commerce platforms all claim to support APIs, but there are vast differences between offerings. commercetools APIs are API first, API only, microservice-backed, cloud native and extensible. Let's look at each in depth.
API First
We have a strict "API first" policy, meaning APIs are modeled before any code is written. Once the API is modeled, we generate both the server-side implementation and client stubs. Our developers then use the auto-generated code as the starting point of their implementation. Method signatures, field names, etc are all fixed, with developers having the freedom to innovate with their implementation of the APIs.
An API first approach has three primary benefits:
- The first benefit is that the APIs are designed for developers, rather than based on how the underlying application works. Many other commerce platforms started with an existing application that was built exclusively for the web. Much of the business logic was built directly into the UI. APIs bolted on to these legacy monolithic commerce platforms weren't designed - they were simply bolted on to what was already there, which pushes more responsibility to the developers. An application whose API is modeled first is always going to be easier to consume.
- The second benefit is that there's consistency in matters large and small. Authentication and authorization is standardized. The number of decimal places for numbers is standardized. The way you specify a local is standardized. Our APIs are consistent because they were designed that way from the start.
- The third benefit is that by default, our API documentation always matches our server-side implementation, which in turn always matches our SDKs. Without a single source of truth from which everything emanates, as a vendor you're left consistently trying to synchronize all three pieces (API documentation, server-side implementation, SDKs). We don't have those problems.
Furthermore, our APIs are Properly modeled using the RAML specification. This widely used specification is robust and comes with a rich ecosystem of supporting commercial and open source products. Our RAML definition is publicly documented on GitHub at https://github.com/commercetools/commercetools-api-reference.
API Only
Next, the functionality in our platform is 100% accessible over APIs. From core product functionality, to imports/exports, to configuration, to system integration, we have 100% API coverage. Absolutely no functionality is available through other means and there's no access to our underlying datastore or search engine.
By definition, a commerce platform built pre-API cannot have 100% API coverage. Not all functionality can be retroactively exposed as an API. With traditional commerce platforms, it's unfortunately too common to have to write a configuration file to a file system, directly access a database, or expose functionality through "hacks" like changing a JSP's response type to JSON because of the embedded business logic.
With an API first and API only approach, there's no need to do complex transformations, build facades, etc. All of the functionality is directly exposed to the consumer.
Finally, our API only approach allows us to have extremely granular authentication and authorization through the use of OAuth scopes. Most applications have authentication only and it's at the perimeter. If you authenticate once, you can access all of the functionality contained within the application. Even if there is more granular API-level authentication, it's not very strong because the application that underlies all of the APIs is all still accessible if there's a security vulnerability or bug. We've designed extremely granular API-level authentication and authorization, which allows administrators to give developers fine-grained access.
Microservice-backed
Next, our APIs are backed by microservices. Microservices are pieces of business functionality that are independently developed, deployed, and managed by a small team of people from different disciplines.
Characteristics of microservices include:
- Single purpose: Do one thing and do it well
- Encapsulation: Each microservice owns its own data. Interaction with the world is through well-defined APIs (often, but not always, HTTP REST)
- Ownership: A single team of 2 to 15 (7, plus or minus 2, is the standard) people develop, deploy, and manage a single microservice through its life cycle
- Autonomy: Each team is able to build and deploy its own microservice at any time for any reason, without having to coordinate with anyone else. Each team also has a lot of freedom in making its own implementation decisions
The advantage of a microservices-based architecture is that the APIs are more easily able to be consumed independently. The shopping cart microservice team, for example, needs to expose an API that can be called by anybody or anything, internally or externally. An API retroactively bolted on top of a monolithic application is inherently less callable because you're consuming a small piece of something much larger. There are always going to be dependencies. To call a shopping cart, for example, you may have to call inventory, pricing, and tax as you retrieve your shopping cart. But a shopping cart developed as a standalone microservice already has those dependencies included.
Because we use microservices, each individual microservice can be deployed, evolved, and scaled independently. With a traditional monolithic application, you have to deploy, evolve and scale the entire application as one indivisible unit. If our pricing API needs a new feature, it can be quickly implemented and released, often in just a few hours or days.
From a commercial standpoint, we support APIs to be purchased independently, with their use metered. Some of our customers use us just as a shopping cart. Some use us for a product catalog. It's really up to the caller. Those API calls can then be metered and paid for incrementally, rather than the traditional approach of a big up-front multi-year licensing agreement.
Cloud Native
In 2012, a group of people within Heroku (now part of Salesforce.com) defined a manifesto defining the 12 principles of modern cloud-based applications. Applications that adhere to these principles are called "12 factor apps." These factors include:
- Codebase: One codebase tracked in revision control system, many deploys
- Dependencies: Explicitly declare and isolate dependencies
- Config: Store config in the environment
- Backing Services: Treat backing services as attached resources
- Build, release, run: Strictly separate build and run stages
- Processes: Execute the app as one or more stateless processes
- Port binding: Export services via port binding
- Concurrency: Scale out via the process model
- Disposability: Maximize robustness with fast startup and graceful shutdown
- Dev/prod parity: Keep development, staging and production as similar as possible
- Logs: Treat logs as event streams
- Admin process: Run admin/management tasks as one-off processes
For more information, check out https://12factor.net.
We work this way internally because it's simply the right way to build apps for cloud. Availability, scalability, bug counts, time to issue resolution, etc are all substantially better because applications built using this methodology are inherently better.
Going beyond 12 factor, we deploy our platform to multiple regions, with multiple availability zones used in each region. If one data center goes down, the other one within the region will get all of the traffic immediately, with auto-scaling kicking in to quickly add additional capacity. This failover process is entirely transparent to your application.
Finally, our APIs are stateless, meaning that no single client request is dependent on the server-side state of a previous request. Any data, including state, is immediately persisted to our data store with each HTTP request, thus ensuring that:
- The failure of any single instance behind the API you're calling won't impact you
- You can easily consume functionality from non-web clients, where support for state may be limited by the type of device. An IoT-style device, for example, may not have enough intelligence to make use of sessions, or have enough local memory to deal with them
- Availability is always best, because we as a provider of the APIs can quickly scale up and down
Following cloud native principles is something we're passionate about at commercetools. While much of this is invisible to you, you will see clear benefits in terms of availability, scalability, bug counts, time to issue resolution and so on.
Extensible
Your business is inherently unique and our APIs will never be able to meet your exact requirements. As a result, you’ll have to extend the APIs you consume. Common extensions include:
- Sending notifications when an event has occurred, like sending an email when order has been shipped
- Capturing additional properties on objects, like capturing a customer’s shoe size on registration
- Validating data, like checking user-submitted data for SQL injection attacks
- Performing real-time data checks, like making sure inventory is available during checkout
- Adjusting the behavior of the API, like changing how prices are calculated
We support four approaches to extending APIs, allowing complete freedom to extend our functionality.
Extension - Extending Data Model Approach
Many customizations are simply a matter of collecting additional attributes or defining custom objects. If you sell shoes, you’ll want to capture the shoe size of your customer upon registration. If you sell auto parts, you’ll want to capture the make/model/year of the customer’s cars.
At commercetools, we offer the ability to add attributes to existing objects:
We also support the ability to define these extensions via APIs.
Extension - Event-Based approach
Many extension use cases can be solved through the use of events. An event is essentially a message with a payload—often a JSON or XML-based representation of an object—like an order or a customer profile.
At commercetools, we offer the ability to subscribe to the internal events that our individual microservices produce. You can push those events out to IronMQ, AWS SQS, AWS SNS, and Azure Service Bus.
Those events can then be passed to little dedicated applications or function-as-a-service style offerings. This is primarily for asynchronous events, like sending an email to a customer after they placed an order.
Extension - Wrapping Approach
There are some extensions that require must be synchronously executed, like calculating how prices are calculated. With this model, you'll wrap calls to commercetools APIs and then execute some code before, after or before and after:
This approach is similar to how traditional commerce platforms are extended.
Extension - Injection Approach
While wrapping calls to commercetools APIs works, there's a new approach to extending APIs that we're pioneering. Rather than having your code call your wrapper, which then calls our API, we will soon offer the ability to inject functionality into our out of the box APIs through the use of function-as-a-service offerings like AWS Lambda:
In this model, you're actually changing how our out-of-the-box APIs work. This allows you to re-use out of-the-box SDKs and it allows all callers of the APIs to consume the new functionality. No re-routing required!
Final Thoughts
It should be clear by now that not all commerce APIs are the same. commercetools is API first, API only, backed by microservices, cloud native, and extensible. Choose your commerce API vendor wisely.
You made it to the end of this article and still want to have more information? Then please check out our latest book APIs for Modern Commerce and download it for free here: https://go.commercetools.com/api-booklet
Remarks: This article was written with support from Kelly Goetsch. Thanks for your effort and help!
Head of Technology - Peppy
6 年Very good read, thank you!