| name | documenso-migration-deep-dive |
| description | 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", "documenso replatform", "replace docusign".
|
| allowed-tools | Read, Write, Edit, Bash(npm:*), Bash(node:*) |
| version | 1.0.0 |
| license | MIT |
| author | Jeremy Longshore <jeremy@intentsolutions.io> |
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 Type | Complexity | Duration | Risk |
|---|
| Fresh start | Low | Days | Low |
| DocuSign migration | Medium | Weeks | Medium |
| HelloSign migration | Medium | Weeks | Medium |
| Adobe Sign migration | High | Months | High |
| Self-hosted migration | Medium | Weeks | Medium |
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
interface MigrationAssessment {
documentsTotal: number;
documentsActive: number;
templatesTotal: number;
integrationPoints: string[];
customizations: string[];
dependencies: string[];
estimatedMigrationHours: number;
}
async function assessCurrentSystem(): Promise<MigrationAssessment> {
const codebaseAnalysis = await analyzeCodebase();
const documentStats = await getCurrentDocumentStats();
const integrations = await findIntegrationPoints();
return {
documentsTotal: documentStats.total,
documentsActive: documentStats.active,
templatesTotal: documentStats.templates,
integrationPoints: integrations,
customizations: codebaseAnalysis.customizations,
dependencies: codebaseAnalysis.dependencies,
: (codebaseAnalysis),
};
}
() {
{
: [
,
,
,
],
: [, ],
};
}
Step 2: Feature Mapping
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: ,
},
{
: ,
: ,
: ,
: ,
},
{
: ,
: ,
: ,
: ,
},
];
Implementation Plan
Phase 1: Setup (Week 1-2)
{
"dependencies": {
"docusign-esign": "^6.0.0",
"@documenso/sdk-typescript": "^0.3.0"
}
}
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>;
}
{
}
{
}
Phase 2: Adapter Implementation (Week 3-4)
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: ,
};
}
(
: ,
:
): <> {
result = ...({
: docId,
: recipient.,
: recipient.,
: .(recipient.),
});
result.!;
}
(: , : ): <> {
result = ...({
: docId,
: field.,
: .(field.),
: field.,
: field.,
: field.,
: field.,
: field.,
});
result.!;
}
(: ): <> {
...({ : docId });
}
(: ): <> {
doc = ...({ : docId });
{
: doc.!,
: .(doc.!),
: doc.?.( ({
: r.!,
: .(r.!),
})) ?? [],
};
}
(: ): <> {
result = ...({
: docId,
});
.(result );
}
(: ): {
: <, > = {
: ,
: ,
: ,
: ,
};
mapping[role.()] ?? ;
}
(: ): {
: <, > = {
: ,
: ,
: ,
: ,
: ,
: ,
: ,
};
mapping[] ?? ;
}
(: ): {
: <, > = {
: ,
: ,
: ,
: ,
: ,
};
mapping[status] ?? status.();
}
(: ): {
: <, > = {
: ,
: ,
: ,
};
mapping[status] ?? ;
}
}
Phase 3: Service Factory with Feature Flags (Week 5)
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> {
const documensoEnabled = await this..();
(documensoEnabled) {
(
...,
...
);
}
percentage = ..();
(.() * < percentage) {
(
...,
...
);
}
(
...,
...
);
}
}
Phase 4: Data Migration (Week 6-7)
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.,
: f.,
: f.,
: f.,
: f.,
: f.,
: f.,
})),
: ,
});
}
fs.(
,
.(plans, , )
);
plans;
}
{
: ;
?: ;
: ;
: ;
?: ;
?: ;
}
(): <> {
db.();
}
Phase 5: Webhook Migration (Week 8)
import express from "express";
const router = express.Router();
router.post("/webhooks/documenso", (req, res) => {
const { event, payload } = req.body;
const normalizedEvent = normalizeDocumensoEvent(event, payload);
processSigningEvent(normalizedEvent);
res.json({ received: true });
});
router.post("/webhooks/docusign", (req, res) => {
const { event, data } = req.body;
const normalizedEvent = normalizeDocuSignEvent(event, data);
processSigningEvent(normalizedEvent);
res.json({ status: "ok" });
});
interface NormalizedSigningEvent {
eventType: "created" | "sent" | "signed" | "completed" | "declined";
documentId: string;
provider: | ;
?: ;
: ;
}
(): <> {
.();
(event.) {
:
(event);
;
:
(event);
;
}
}
Phase 6: Rollout & Monitoring (Week 9-10)
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" },
];
interface MigrationMetrics {
documentsCreated: { legacy: number; documenso: number };
errorRate: { legacy: number; documenso: number };
latencyP95: { legacy: number; : };
: { : ; : };
}
(): <{
: ;
: ;
}> {
metrics = ();
errorDiff = metrics.. - metrics..;
healthy = errorDiff < ;
{ healthy, metrics };
}
Rollback Procedure
#!/bin/bash
echo "Rolling back Documenso migration..."
curl -X POST $FEATURE_FLAG_API/flags \
-d '{"flag": "documenso_rollout", "value": 0}'
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 Issue | Cause | Solution |
|---|
| Field mapping failed | Different coordinates | Adjust position calculation |
| Webhook format | Different payload | Normalize events |
| Template missing | Not recreated | Create in Documenso |
| High error rate | Integration bug | Pause rollout, investigate |
Resources
Congratulations!
You have completed the Documenso Skill Pack. Review other skills as needed for ongoing operations.