Skip to main content
Skip table of contents

Advanced API Endpoint Deprecation Guidance

Last Updated: April 30, 2025

As API requirements evolve, it's critical to have a clear and well documented strategy for deprecating endpoints to avoid introducing technical debt, broken integrations, or confusion across Platform and VFS teams. While the high level checklist outlines the basic steps, this advanced guidance dives deeper into best practices specifically tailored to Vets API and specifically Rails applications. It includes concrete examples, detailed explanations, and strategies for managing timelines, toggles, logging, and communication. The goal is to help teams deprecate endpoints cleanly, safely, and with full visibility, while maintaining consistency across team dependencies.

Advanced Guidance

⏲️ Timelines & Deprecation Lifecycle

Establishing a structured deprecation timeline is essential to prevent orphaned endpoints, reduce complexity, and ensure a predictable experience for API consumers. Without a defined approach, legacy code tends to linger, leading to confusion, inconsistent behavior, and increased maintenance burden.

Phase

Description

Duration

Announcement

Inform stakeholders via Slack, and link relevant documentation. Mark deprecated in Swagger.

At least 30-90 days before enforcement

Deprecated (Soft)

Endpoint is still functional but returns a deprecation warning. Track usage.

30–90 days

Deprecated (Hard)

Endpoint remains available but triggers alerts if still being used. Begin feature flag cleanup.

15–30 days

Removal

Endpoint is removed from the codebase and Swagger. Any consumers not migrated are broken.

🚦 Endpoints

In line with Rails conventions, avoid modifying existing controller actions or routes directly when integrating a new service. Instead, follow the Rails norm of introducing new, RESTful endpoints or namespaced routes that cleanly separate legacy behavior from new logic. This preserves clarity in routing and prevents unnecessary churn in existing code paths.

Clearly Mark Deprecated Endpoints in the Controller

In keeping with the Rails focus on readable and maintainable code, deprecated controller actions should be explicitly marked with a comment block. Include the deprecation notice, removal timeline, and reference to the replacement if applicable. This informs future developers of the intent and prevents misuse.

RUBY
# app/controllers/v0/sample_controller.rb
class V0::SampleController < ApplicationController
  # DEPRECATED: This endpoint is tied to the legacy sample system.
  # Will be removed on or after 2025-06-30.
  # Use V1::SampleController#index instead.
  def index
    render json: LegacySampleService.fetch(current_user)
  end
end

Return a Deprecation Warning in the Response (Optional)

Rails allows you to inject headers into responses via controller actions or concerns. Including a Deprecation header is a non-breaking way to inform consumers that the endpoint is outdated.

RUBY
def index
  response.set_header('Deprecation', 'This endpoint is deprecated and will be removed by 2025-06-30')
  render json: LegacySampleService.fetch(current_user)
end

Add a Clear Timeline for Removal

Timelines should be documented both in code (via comments - if applicable) and in artifacts like Github tickets, product roadmaps and API docs. This aligns with Rails norms around transparency and version aware changes. While Rails doesn’t enforce deprecation timelines, it’s good practice to tie deprecations to specific deployments or feature flags and consistently document the dates in code and communications.

Update Swagger Docs

For Vets API (using Swagger docs), it’s important to reflect deprecated endpoints in API specs. Mark deprecated endpoints with the deprecated: true flag and add context to the description to point users to alternatives.

YAML
paths:
  /v0/sample:
    get:
      summary: Retrieve legacy sample (DEPRECATED)
      deprecated: true
      description: |
        This endpoint is tied to the legacy sample system and will be removed by 2025-06-30.
        Please migrate to /v1/sample.

This keeps docs aligned with Rails best practice of keeping documentation version controlled and discoverable alongside the source.

Isolate Legacy Endpoints Behind a Version Namespace

Following Rails routing best practices, deprecated or legacy endpoints should be grouped under a dedicated version namespace to clearly signal that they are no longer actively maintained.

This versioning structure allows for teams to adjust and roll out the new version independently while continuing to serve the legacy traffic during the migration window. It also simplifies toggling and log filtering, which is helpful when testing and monitoring new integrations.

Example: config/routes.rb

RUBY
namespace :v0 do
  resources :samples, only: [:index, :show]
end
namespace :v1 do
  resources :samples, only: [:index, :show]
end

📣 Communication Strategy

Effective communication is essential to a smooth endpoint deprecation process. While Vets API deprecation warnings and API response headers provide immediate visibility to consumers, they should be paired with broader communication efforts. These include proactive messaging in OCTO Slack channels, stakeholder engagement, and participation in cross-team collaboration meetings such as Team of Teams. It’s important to document, roadmap and communicate key dates (such as deprecation announcements), migration deadlines, and removal timelines consistently across all channels and within the codebase itself. This ensures transparency, sets clear expectations, and reduces the likelihood of downstream disruptions.

🔀 Dual Routing & Parallel Behavior

Use a Feature Toggle for Dual Service Testing

Vets API uses Flipper for runtime feature toggles. When deprecating an endpoint, a feature toggle can help control access based on user groups, rollout percentage, or environment. This provides flexibility to gradually phase out an endpoint, monitor remaining usage, and allow for rollback without redeploying code.

RUBY
def index
  if Flipper.enabled?(:disable_v0_sample_endpoint, current_user)
    render json: { warning: "This endpoint is deprecated" }, status: :gone
  else
    result = V0::SampleService.fetch(current_user)
    render json: result
  end
end

Use toggles to:

  • Disable an endpoint for select users while allowing others to continue using it temporarily

  • Show deprecation warnings without fully removing functionality

  • Gradually reduce traffic before permanent removal

This provides safer transitions and supports better communication and observability during deprecation phases. See the Feature Toggles Guide for additional information.

🔍 Tracking Traffic & Behavior

Understanding how an endpoint is used by consumers is critical before deprecation. Datadog APM can be leveraged to track request volume, error rates, and latency over time. Pairing a feature toggle with dual routing enables teams to safely compare usage between the old and new paths in parallel. Even if the endpoint is being fully removed without a replacement, it’s important to monitor request volume to understand impact. Creating a dedicated Datadog dashboard or notebook for the deprecated endpoint can provide valuable insights and historical trends to inform timing, communication, and removal validation. Tracking behavior ensures teams can make data informed decisions and reduces the risk of unnoticed breakage.

🧼 Code Hygiene and Other Cleanup

As part of a healthy endpoint deprecation process, teams should prioritize codebase hygiene to reduce technical debt and improve long term maintainability. Once an endpoint is marked for deprecation, attention should shift toward identifying and isolating related code paths, removing deprecated patterns, and ensuring test coverage reflects the current logic. The following sections outline recommended practices to ensure a clean and consistent deprecation lifecycle.

Dead Code Cleanup and Audit

During the endpoint deprecation process, legacy endpoints, routes, modules, and helpers that are no longer in use can linger in the codebase, increasing maintenance risk and developer confusion. Teams should proactively surface and evaluate these remnants using things like commit history, GitHub search, or tools like GitHub Copilot to identify deprecated patterns or unused references.

It may be a good idea to complement the above auditing advice with Datadog metrics, log audits, and feature toggle usage to confirm whether an endpoint is still receiving traffic. Prioritize removal of any endpoint code paths that are no longer active to ensure a cleaner codebase in Vets API.

Test Suite Updates

With functionality moving or changing, it’s critical to align the test suite. Remove stale specs tied to deprecated endpoints or models. Focus on system and request specs to ensure integrations continue to behave correctly. This is also a good opportunity to restructure large or brittle specs for improved readability and maintainability.

Pay special attention to outdated VCR cassettes, stubbed requests, and mock data that may no longer be relevant as these can cause false positives and increase test maintenance overhead. Cleaning these up improves test accuracy and reduces long term maintenance overhead.

Deprecate Unused Classes, Endpoints, Serializers, and Service Object Patterns

Audit your app’s lib/services, app/serializers, and controller routes to identify unused functionality tied to the endpoint deprecation. Mark deprecated patterns clearly in the code (using comments or ActiveSupport::Deprecation.warn) to plan and schedule their removal.

Documentation When Teams Roll Off of a Contract

Before a VFS team exits a contract, documentation should be finalized and handed off in a way that ensures continuity for incoming teams or stakeholders. This includes detailed system overviews, architectural diagrams, integration points, and known issues. All relevant docs should be stored in an accessible location (either source code repos, Github or Confluence), and ownership of critical components should be clearly identified. Teams should leave behind actionable notes on in progress items, dependencies, and any issues that aren’t obvious from the codebase itself. A documented handoff plan helps maintain institutional knowledge and reduces the onboarding burden for future contributors.

✏️ Update Docs and Share Widely

When a endpoint is being deprecated, added or replaced, it’s important to proactively update any public or shared documentation that references it. Documentation should reflect the current state of any service (including external services) and integration points. It’s important to clearly mark deprecated features and provide guidance on migrating to the new approach. Changes should be shared through multiple avenues (Slack channels, product update meetings, such as Team of Teams, etc). Keeping documentation up to date reduces confusion for Platform and VFS teams, aligns expectations, and helps coordinate transition.


JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.