Best design options to easily change backends for subset of consumers

A problem recently came up with a customer that may also come up for you. I’ll state the problem and then walk through a number of different possible solutions, all with their own pros and cons. Based on your own scenario, you may find that a different solution will work better for you.

Problem: As an Apigee proxy developer/architect, I would like to best architect API proxies so that I can modify the backend URLs for a given resource for subset of API consumers. API consumers will have their own unique domains that they use to access the APIs.

To have the same context throughout, here is some material we can use to work with:

Consumer Groups that represent groups of consumers that access resources at the same domain for that consumer group:

consumer group A

consumer group B

The backends that may change out:

Backend A

Backend B

Solutions: This may sound like a simple problem on its surface, but as we dig in deeper, we’ll see the seams. It’s at those seams that we will have to pick and choose what advantages we want and what concerns we can accept. Let’s start with a bad solution and work from there.

A Bad Solution:

Create a single proxy for resource1 with multiple target endpoints to accommodate for each API Consumer Group. All virtual hosts are included in the proxy endpoint for that proxy. If a backend URL needs to change for a consumer group, update the target endpoint and redeploy the proxy. E.g., consumer group A and consumer group B both use backend X. Target endpoint 1 (for consumer group A) and target endpoint 2 (for consumer group B) both point to backend X. But now there is a change required where consumer group A needs to use backend X and consumer group B needs to use backend Y, and so target endpoint 2 is updated and the whole proxy is redeployed.

Why is this bad? Every time a backend needs to change for 1 consumer group, all other consumer groups are also affected because they all share the same proxy. This causes unnecessary downtime. In addition, this design introduces unnecessary risk by requiring changes to a proxy that may affect consumer groups that are not changing. Also, this design is brittle since the proxy endpoint is shared between all consumer groups. You could try to push that logic to the target endpoint, but you lose the flexibility in the proxy endpoint. Last, this proxy will be huge and will keep growing with additional consumer groups; it may take a long time for the supporting runtime infrastructure to load such a large proxy bundle (and worse yet, many of them!).

Better Solutions: Here are other solutions that are better, but each has their own drawbacks. Which one did we use in the end? You’ll have to read on to find out.

Option A

A. Reserve an environment per consumer group. In this solution, the vhost name will be the same (e.g., vhost1), but the vhost will map to a different domain name in each environment (this is out-of-the-box in Edge). As a change in target URL is required, create a new revision and deploy that new revision to the corresponding environment.

    1. Pros
    1. Easy to debug issue since you have completely separate environments
    2. You can use a single proxy across all consumer groups, but you can also modify them per consumer group as needed. To do this, create a new proxy with the same basepath and modify as needed.
  1. Cons
    1. There are many more environments to manage. This may mean more environment-level entities (e.g., environment-level caches).
    2. Analytics across environments needs to be aggregated.
    3. Products will multiply by number of environments.
    4. Need to keep track of which revision corresponds to which consumer group and environments.

Option B

B. Create 2 proxy layers with the first layer directing to the appropriate proxy in the second layer. Can use KVM/JS to maintain mapping relationship between proxy layers so that redeployment isn’t required with changes. The first proxy layer can be varying levels of abstraction: a single proxy for all proxies or 2-to-n set of proxies than fan out to the second layer where n is the total number of resources. The first proxy layer could also employ multiple target endpoints depending on how much flexibility is needed (e.g., if you wish to use proxy chaining).

  1. Pros
    1. Clear distinction between changes in proxies since the second layer of proxies is distinct between each set of changes.
    2. Less reliance on vhost and environment manipulation.
    3. Have a lot of proxy design flexibility due to separation of layers.
    4. Analytics will be clean and will make for easy-to-read reports when separating traffic for various changes like different backends.
  2. Cons
    1. With proxy chaining, may incur double count of APIs.
    2. Harder to debug due to multiple layers where things can go wrong.
    3. Maintain separate backend proxy layer versions as separate proxies which may lead to multiple versions of related entities (caches, target servers, KVMs, etc.).
    4. This design will create a lot of proxies, i.e., multiple proxies for each version for each consumer group or set of consumer groups.
    5. Authorization is trickier because traffic may need authorization in the 2nd layer.
    6. You may need more products if you really want to isolate consumer group usage from each other (recommended).

Option C

C. 1 vhost per consumer group with a separate proxy per consumer group for a given resource (e.g., proxy1-consumergroupA, resource1-consumergroupB, etc.).

  1. Pros
    1. A specific consumer group’s proxy can be changed individually without affecting other consumer group’s proxies.
    2. Analytics are combined at the environment level.
  2. Cons
    1. Many more proxies: total number of proxies = (number of proxies) * (number of consumer groups).
    2. You may also need many more products if you really want to isolate consumer group usage from each other (recommended).
    3. Analytics need to be combined for a given resource since proxies will be multiplied by the number of consumer groups.

Option D

D. 1 vhost per consumer group with a single proxy shared across consumer groups - rearrange vhost assignments in proxy revisions. When a consumer group, as represented by its own vhost, needs to be partitioned out, create a new revision with the new vhosts separated out.

  1. Pros
    1. Less proxies, less environments, and less products.
    2. Easier to follow most analytics as-is, though changes as revisions are harder to track.
  2. Cons
    1. Requires redeployment of all consumer groups upon any change with 1 consumer group. You’ll need to update the old revision to remove the changing consumer groups, and you’ll need to deploy the new revision that adds the changing consumer groups.

And so where did we end up? Turns out we went with option A since it was easiest to manage and had clear separation between environments. It also didn’t have huge problems like option D. Your mileage may vary, as your requirements and what pros/cons are most important to you will change your decision making.

Please post feedback, as we’d love to hear your thoughts.

Version history
Last update:
‎02-10-2020 03:49 PM
Updated by: