Skip to content
documenso-migration-deep-dive logo

Documenso Migration Deep Dive

documenso-migration-deep-dive

Execute comprehensive Documenso migration strategies for platform switches. Use when migrating from other signing platforms, re-platforming to Documenso, or performing major infrastructure changes. Trigger with phrases like "migrate to documenso", "documenso migration", "switch to documenso", "do...

SKILL.md

Full skill instructions

Documenso Migration Deep Dive

Overview

Comprehensive guide for migrating to Documenso from other e-signature platforms or implementing major architectural changes.

Prerequisites

  • Current system documentation
  • Documenso account configured
  • Feature flag infrastructure
  • Rollback strategy tested

Migration Types

Migration TypeComplexityDurationRisk
Fresh startLowDaysLow
DocuSign migrationMediumWeeksMedium
HelloSign migrationMediumWeeksMedium
Adobe Sign migrationHighMonthsHigh
Self-hosted migrationMediumWeeksMedium

Migration Strategy: Strangler Fig Pattern

Phase 1: Parallel Systems
┌─────────────────────────────────────────────────────────┐
│ Your Application                                         │
│  ┌─────────────┐         ┌─────────────┐               │
│  │   Legacy    │  100%   │  Documenso  │   0%         │
│  │  (DocuSign) │ ◀────── │   (New)     │              │
│  └─────────────┘         └─────────────┘               │
└─────────────────────────────────────────────────────────┘

Phase 2: Traffic Shifting
┌─────────────────────────────────────────────────────────┐
│ Your Application                                         │
│  ┌─────────────┐         ┌─────────────┐               │
│  │   Legacy    │  50%    │  Documenso  │   50%        │
│  │  (DocuSign) │ ◀─────▶ │   (New)     │              │
│  └─────────────┘         └─────────────┘               │
└─────────────────────────────────────────────────────────┘

Phase 3: Complete Migration
┌─────────────────────────────────────────────────────────┐
│ Your Application                                         │
│  ┌─────────────┐         ┌─────────────┐               │
│  │   Legacy    │   0%    │  Documenso  │  100%        │
│  │  (Retired)  │ ──────▶ │   (Active)  │              │
│  └─────────────┘         └─────────────┘               │
└─────────────────────────────────────────────────────────┘

Pre-Migration Assessment

Step 1: Document Current State

// scripts/​analyze-current-system.ts
interface MigrationAssessment {
  documentsTotal: number;
  documentsActive: number;
  templatesTotal: number;
  integrationPoints: string[];
  customizations: string[];
  dependencies: string[];
  estimatedMigrationHours: number;
}

async function assessCurrentSystem(): Promise<MigrationAssessment> {
  // Analyze existing integration
  const codebaseAnalysis = await analyzeCodebase();

  // Count documents and templates
  const documentStats = await getCurrentDocumentStats();

  // Identify integration points
  const integrations = await findIntegrationPoints();

  return {
    documentsTotal: documentStats.total,
    documentsActive: documentStats.active,
    templatesTotal: documentStats.templates,
    integrationPoints: integrations,
    customizations: codebaseAnalysis.customizations,
    dependencies: codebaseAnalysis.dependencies,
    estimatedMigrationHours: calculateEstimate(codebaseAnalysis),
  };
}

async function analyzeCodebase() {
  // Find all files using signing service
  // grep -r "docusign\|hellosign\|adobe.sign" src/

  return {
    customizations: [
      "Custom email templates",
      "Webhook processing",
      "PDF preprocessing",
    ],
    dependencies: ["@docusign/​esign", "docusign-esign"],
  };
}

Step 2: Feature Mapping

// Map existing features to Documenso equivalents
interface FeatureMapping {
  existingFeature: string;
  documensoEquivalent: string;
  migrationNotes: string;
  complexity: "low" | "medium" | "high";
}

const FEATURE_MAPPING: FeatureMapping[] = [
  {
    existingFeature: "DocuSign envelope",
    documensoEquivalent: "Documenso document/​envelope",
    migrationNotes: "Direct mapping, similar concept",
    complexity: "low",
  },
  {
    existingFeature: "DocuSign template",
    documensoEquivalent: "Documenso template",
    migrationNotes: "Recreate templates, export/​import not supported",
    complexity: "medium",
  },
  {
    existingFeature: "PowerForms",
    documensoEquivalent: "Direct templates",
    migrationNotes: "Use Documenso direct template links",
    complexity: "low",
  },
  {
    existingFeature: "Bulk send",
    documensoEquivalent: "Batch API calls",
    migrationNotes: "Implement batch processing with queue",
    complexity: "medium",
  },
  {
    existingFeature: "Connect (webhooks)",
    documensoEquivalent: "Documenso webhooks",
    migrationNotes: "Similar events, different payload structure",
    complexity: "medium",
  },
  {
    existingFeature: "Embedded signing",
    documensoEquivalent: "Embed components",
    migrationNotes: "Use @documenso/​embed-react or similar",
    complexity: "low",
  },
];

Implementation Plan

Phase 1: Setup (Week 1-2)

// Step 1: Install Documenso SDK alongside existing
// package.json
{
  "dependencies": {
    // Keep existing
    "docusign-esign": "^6.0.0",
    // Add Documenso
    "@documenso/​sdk-typescript": "^0.3.0"
  }
}

// Step 2: Create unified interface
// src/​signing/​interface.ts
export interface SigningService {
  createDocument(input: CreateDocumentInput): Promise<DocumentResult>;
  addRecipient(docId: string, recipient: RecipientInput): Promise<string>;
  addField(docId: string, field: FieldInput): Promise<string>;
  sendDocument(docId: string): Promise<void>;
  getDocumentStatus(docId: string): Promise<DocumentStatus>;
  downloadDocument(docId: string): Promise<Buffer>;
}

// Step 3: Implement adapters
// src/​signing/​adapters/​docusign.ts
export class DocuSignAdapter implements SigningService {
  // Existing implementation
}

// src/​signing/​adapters/​documenso.ts
export class DocumensoAdapter implements SigningService {
  // New implementation
}

Phase 2: Adapter Implementation (Week 3-4)

// src/​signing/​adapters/​documenso.ts
import { Documenso } from "@documenso/​sdk-typescript";
import { SigningService, CreateDocumentInput } from "../​interface";

export class DocumensoAdapter implements SigningService {
  private client: Documenso;

  constructor(apiKey: string, baseUrl?: string) {
    this.client = new Documenso({
      apiKey,
      serverURL: baseUrl,
    });
  }

  async createDocument(input: CreateDocumentInput): Promise<DocumentResult> {
    const doc = await this.client.documents.createV0({
      title: input.title,
      file: input.file,
    });

    return {
      id: doc.documentId!,
      status: "DRAFT",
      provider: "documenso",
    };
  }

  async addRecipient(
    docId: string,
    recipient: RecipientInput
  ): Promise<string> {
    const result = await this.client.documentsRecipients.createV0({
      documentId: docId,
      email: recipient.email,
      name: recipient.name,
      role: this.mapRole(recipient.role),
    });

    return result.recipientId!;
  }

  async addField(docId: string, field: FieldInput): Promise<string> {
    const result = await this.client.documentsFields.createV0({
      documentId: docId,
      recipientId: field.recipientId,
      type: this.mapFieldType(field.type),
      page: field.page,
      positionX: field.x,
      positionY: field.y,
      width: field.width,
      height: field.height,
    });

    return result.fieldId!;
  }

  async sendDocument(docId: string): Promise<void> {
    await this.client.documents.sendV0({ documentId: docId });
  }

  async getDocumentStatus(docId: string): Promise<DocumentStatus> {
    const doc = await this.client.documents.getV0({ documentId: docId });

    return {
      id: doc.id!,
      status: this.mapStatus(doc.status!),
      recipients: doc.recipients?.map((r) => ({
        email: r.email!,
        status: this.mapRecipientStatus(r.signingStatus!),
      })) ?? [],
    };
  }

  async downloadDocument(docId: string): Promise<Buffer> {
    const result = await this.client.documents.downloadV0({
      documentId: docId,
    });
    return Buffer.from(result as ArrayBuffer);
  }

  private mapRole(role: string): string {
    const mapping: Record<string, string> = {
      signer: "SIGNER",
      cc: "CC",
      viewer: "VIEWER",
      approver: "APPROVER",
    };
    return mapping[role.toLowerCase()] ?? "SIGNER";
  }

  private mapFieldType(type: string): string {
    const mapping: Record<string, string> = {
      signHere: "SIGNATURE",
      initialHere: "INITIALS",
      dateSigned: "DATE",
      fullName: "NAME",
      email: "EMAIL",
      text: "TEXT",
      checkbox: "CHECKBOX",
    };
    return mapping[type] ?? "TEXT";
  }

  private mapStatus(status: string): string {
    const mapping: Record<string, string> = {
      DRAFT: "draft",
      PENDING: "sent",
      COMPLETED: "completed",
      CANCELLED: "voided",
      REJECTED: "declined",
    };
    return mapping[status] ?? status.toLowerCase();
  }

  private mapRecipientStatus(status: string): string {
    const mapping: Record<string, string> = {
      NOT_SIGNED: "pending",
      SIGNED: "completed",
      REJECTED: "declined",
    };
    return mapping[status] ?? "pending";
  }
}

Phase 3: Service Factory with Feature Flags (Week 5)

// src/​signing/​factory.ts
import { SigningService } from "./​interface";
import { DocuSignAdapter } from "./​adapters/​docusign";
import { DocumensoAdapter } from "./​adapters/​documenso";

interface FeatureFlags {
  isEnabled(flag: string): Promise<boolean>;
  getPercentage(flag: string): Promise<number>;
}

export class SigningServiceFactory {
  constructor(
    private featureFlags: FeatureFlags,
    private config: {
      docusign: { apiKey: string; accountId: string };
      documenso: { apiKey: string; baseUrl?: string };
    }
  ) {}

  async getService(context?: { userId?: string }): Promise<SigningService> {
    // Check if fully migrated
    const documensoEnabled = await this.featureFlags.isEnabled("documenso_full");
    if (documensoEnabled) {
      return new DocumensoAdapter(
        this.config.documenso.apiKey,
        this.config.documenso.baseUrl
      );
    }

    // Check gradual rollout percentage
    const percentage = await this.featureFlags.getPercentage("documenso_rollout");
    if (Math.random() * 100 < percentage) {
      return new DocumensoAdapter(
        this.config.documenso.apiKey,
        this.config.documenso.baseUrl
      );
    }

    // Default to legacy
    return new DocuSignAdapter(
      this.config.docusign.apiKey,
      this.config.docusign.accountId
    );
  }
}

Phase 4: Data Migration (Week 6-7)

// scripts/​migrate-templates.ts
/​**
 * Templates cannot be directly exported/​imported.
 * This script documents existing templates for manual recreation.
 */

interface TemplateMigrationPlan {
  legacyTemplateId: string;
  name: string;
  description: string;
  recipientRoles: string[];
  fields: FieldDefinition[];
  recreated: boolean;
  documensoTemplateId?: string;
}

async function generateTemplateMigrationPlan(): Promise<TemplateMigrationPlan[]> {
  const legacyTemplates = await getLegacyTemplates();
  const plans: TemplateMigrationPlan[] = [];

  for (const template of legacyTemplates) {
    plans.push({
      legacyTemplateId: template.id,
      name: template.name,
      description: template.description,
      recipientRoles: template.recipients.map((r) => r.roleName),
      fields: template.fields.map((f) => ({
        type: f.type,
        page: f.pageNumber,
        x: f.xPosition,
        y: f.yPosition,
        width: f.width,
        height: f.height,
        recipientRole: f.recipientRole,
      })),
      recreated: false,
    });
  }

  // Save plan for tracking
  await fs.writeFile(
    "migration/​template-plan.json",
    JSON.stringify(plans, null, 2)
  );

  return plans;
}

// For completed documents, create reference mapping
interface DocumentMapping {
  legacyId: string;
  documensoId?: string;
  title: string;
  status: string;
  completedAt?: string;
  signedDocumentUrl?: string;
}

async function createDocumentMapping(): Promise<void> {
  // Historical documents stay in legacy system
  // New documents go to Documenso
  // Create mapping table for reference

  await db.execute(`
    CREATE TABLE IF NOT EXISTS document_mapping (
      id SERIAL PRIMARY KEY,
      legacy_id VARCHAR(255),
      documenso_id VARCHAR(255),
      title VARCHAR(500),
      status VARCHAR(50),
      completed_at TIMESTAMP,
      created_at TIMESTAMP DEFAULT NOW()
    )
  `);
}

Phase 5: Webhook Migration (Week 8)

// src/​webhooks/​unified-handler.ts
import express from "express";

const router = express.Router();

// New Documenso webhook endpoint
router.post("/​webhooks/​documenso", (req, res) => {
  const { event, payload } = req.body;

  // Normalize to common event format
  const normalizedEvent = normalizeDocumensoEvent(event, payload);
  processSigningEvent(normalizedEvent);

  res.json({ received: true });
});

// Keep legacy webhook endpoint during migration
router.post("/​webhooks/​docusign", (req, res) => {
  const { event, data } = req.body;

  // Normalize to common event format
  const normalizedEvent = normalizeDocuSignEvent(event, data);
  processSigningEvent(normalizedEvent);

  res.json({ status: "ok" });
});

// Common event processing
interface NormalizedSigningEvent {
  eventType: "created" | "sent" | "signed" | "completed" | "declined";
  documentId: string;
  provider: "documenso" | "docusign";
  signerEmail?: string;
  timestamp: Date;
}

async function processSigningEvent(event: NormalizedSigningEvent): Promise<void> {
  console.log(`Processing ${event.provider} event: ${event.eventType}`);

  switch (event.eventType) {
    case "completed":
      await handleDocumentCompleted(event);
      break;
    case "declined":
      await handleDocumentDeclined(event);
      break;
    // ... other handlers
  }
}

Phase 6: Rollout & Monitoring (Week 9-10)

// Gradual rollout schedule
const ROLLOUT_SCHEDULE = [
  { day: 1, percentage: 5, description: "Internal users" },
  { day: 3, percentage: 10, description: "Early adopters" },
  { day: 7, percentage: 25, description: "Quarter traffic" },
  { day: 14, percentage: 50, description: "Half traffic" },
  { day: 21, percentage: 75, description: "Most traffic" },
  { day: 28, percentage: 100, description: "Full migration" },
];

// Monitoring during rollout
interface MigrationMetrics {
  documentsCreated: { legacy: number; documenso: number };
  errorRate: { legacy: number; documenso: number };
  latencyP95: { legacy: number; documenso: number };
  completionRate: { legacy: number; documenso: number };
}

async function checkMigrationHealth(): Promise<{
  healthy: boolean;
  metrics: MigrationMetrics;
}> {
  const metrics = await collectMetrics();

  // Alert if Documenso error rate is significantly higher
  const errorDiff = metrics.errorRate.documenso - metrics.errorRate.legacy;
  const healthy = errorDiff < 0.02; // 2% tolerance

  return { healthy, metrics };
}

Rollback Procedure

#!/​bin/​bash
# scripts/​rollback-migration.sh

echo "Rolling back Documenso migration..."

# Disable Documenso via feature flag
curl -X POST $FEATURE_FLAG_API/​flags \
  -d '{"flag": "documenso_rollout", "value": 0}'

# Verify rollback
sleep 10
curl -s https://your-app.com/​health | jq '.signing.provider'

echo "Rollback complete. All traffic now using legacy provider."

Output

  • Migration assessment complete
  • Unified interface implemented
  • Gradual rollout configured
  • Rollback procedure tested

Error Handling

Migration IssueCauseSolution
Field mapping failedDifferent coordinatesAdjust position calculation
Webhook formatDifferent payloadNormalize events
Template missingNot recreatedCreate in Documenso
High error rateIntegration bugPause rollout, investigate

Resources

Congratulations!

You have completed the Documenso Skill Pack. Review other skills as needed for ongoing operations.

More skills from Dicklesworthstone

environment-setup-guide logo
Dicklesworthstone/pi_agent_rust

environment-setup-guide

Guide developers through setting up development environments with proper tools, dependencies, and configurations

1.8K 0
View
exa-policy-guardrails logo
Dicklesworthstone/pi_agent_rust

exa-policy-guardrails

Implement Exa lint rules, policy enforcement, and automated guardrails. Use when setting up code quality rules for Exa integrations, implementing pre-commit hooks, or configuring CI policy checks for Exa best practices. Trigger with phrases like "exa policy", "exa lint", "exa guardrails", "exa be...

1.8K 0
View
documenso-ci-integration logo
Dicklesworthstone/pi_agent_rust

documenso-ci-integration

Configure CI/CD pipelines for Documenso integrations. Use when setting up automated testing, deployment pipelines, or continuous integration for Documenso projects. Trigger with phrases like "documenso CI", "documenso GitHub Actions", "documenso pipeline", "documenso automated testing".

1.8K 0
View
openrouter-model-availability logo
Dicklesworthstone/pi_agent_rust

openrouter-model-availability

Build check model availability and implement fallback chains. Use when building resilient systems or handling model outages. Trigger with phrases like 'openrouter availability', 'openrouter fallback', 'openrouter model down', 'openrouter health check'.

1.8K 0
View
langfuse-enterprise-rbac logo
Dicklesworthstone/pi_agent_rust

langfuse-enterprise-rbac

Configure Langfuse enterprise organization management and access control. Use when implementing team access controls, configuring organization settings, or setting up role-based permissions for Langfuse projects. Trigger with phrases like "langfuse RBAC", "langfuse teams", "langfuse organization"...

1.8K 0
View
cursor-compliance-audit logo
Dicklesworthstone/pi_agent_rust

cursor-compliance-audit

Execute compliance and security auditing for Cursor usage. Triggers on "cursor compliance", "cursor audit", "cursor security review", "cursor soc2", "cursor gdpr". Use when analyzing or auditing cursor compliance audit. Trigger with phrases like "cursor compliance audit", "cursor audit", "cursor".

1.8K 0
View
apollo-ci-integration logo
Dicklesworthstone/pi_agent_rust

apollo-ci-integration

Configure Apollo.io CI/CD integration. Use when setting up automated testing, continuous integration, or deployment pipelines for Apollo integrations. Trigger with phrases like "apollo ci", "apollo github actions", "apollo pipeline", "apollo ci/cd", "apollo automated tests".

1.8K 0
View
python-script logo
Dicklesworthstone/pi_agent_rust

python-script

Create robust Python automation with full logging and safety checks. Use when tasks need complex data processing, authenticated API work, conditional file operations, or error handling beyond simple shell commands.

1.8K 0
View
posthog-multi-env-setup logo
Dicklesworthstone/pi_agent_rust

posthog-multi-env-setup

Configure PostHog across development, staging, and production environments. Use when setting up multi-environment deployments, configuring per-environment secrets, or implementing environment-specific PostHog configurations. Trigger with phrases like "posthog environments", "posthog staging", "po...

1.8K 0
View
ai-agents-architect logo
Dicklesworthstone/pi_agent_rust

ai-agents-architect

Expert in designing and building autonomous AI agents. Masters tool use, memory systems, planning strategies, and multi-agent orchestration. Use when: build agent, AI agent, autonomous agent, tool use, function calling.

1.8K 0
View
insecure-deserialization-checker logo
Dicklesworthstone/pi_agent_rust

insecure-deserialization-checker

Validate insecure deserialization checker operations. Auto-activating skill for Security Fundamentals. Triggers on: insecure deserialization checker, insecure deserialization checker Part of the Security Fundamentals skill category. Use when working with insecure deserialization checker functiona...

1.8K 0
View
path-traversal-finder logo
Dicklesworthstone/pi_agent_rust

path-traversal-finder

Manage path traversal finder operations. Auto-activating skill for Security Fundamentals. Triggers on: path traversal finder, path traversal finder Part of the Security Fundamentals skill category. Use when working with path traversal finder functionality. Trigger with phrases like "path traversa...

1.8K 0
View

Popular AI tools

Kaiber logo
Video

Kaiber

Generate, edit, and beat-sync AI video with leading models in one workspace.

Paid
View
Vimcal logo
Productivity

Vimcal

The world's fastest calendar for remote work

Free
View

Transform Your Design with AI Designer by ImgCreator.ai

Freemium
View
Akool AI logo
Content & writing

Akool AI

Revolutionizing Video Production with AI-Powered Creativity

Paid
View

Extend an image past the frame and let AI fill the new aspect ratio.

Freemium
View
StarByFace logo
Security

StarByFace

Discover your celebrity doppelgänger with StarByFace!

Free
View
C

ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.

Freemium
View
Opus Clip logo
Coding & apps

Opus Clip

Opus.ai: Revolutionize Your Web Experience

Free
View