# Code migrations

Code migrations can be of a few flavors - upgrading a library (e.g. SQLAlchemy 1.4 to 2.0 in python), upgrading a language framework (Java 8 to Java 17) or migrating to a completely new framework (Ember to React).

Typically large migrations can require multiple teams collaboration and may be spread over a huge amount of codebase. Using Runbooks these migrations can be planned out with all teams involved and executed step by step while ensuring compatibility.

Remote Agents framework also comes pre-bundled with a [library of Runbook templates](mailto:undefined) that can be used as a starting point while adding more context of the nuances associated with your own codebase.

### When to use

#### Ideal scenarios

* **Framework upgrades**: Moving to newer versions of React, Angular, Vue, or other frameworks
* **Language migrations**: Converting from one programming language to another
* **Architecture evolution**: Moving from monolith to microservices or updating patterns
* **Technology stack modernization**: Updating to modern tools and best practices
* **Platform migrations**: Moving between cloud platforms or infrastructure patterns

#### Perfect for teams that

* Need to upgrade legacy applications to modern frameworks
* Want to adopt new technologies without rewriting everything from scratch
* Have tight deadlines for technology updates
* Need to maintain functionality during migration
* Want to minimize migration risks and ensure consistency

### Pre-built migration templates

#### Frontend framework migrations examples

**React Migration Templates**

* **React 16 to 18**: Updates React APIs, lifecycle methods, and new features
* **Class components to hooks**: Converts class-based components to functional components
* **Enzyme to react testing library**: Updating the rendering and quering method
* **PropTypes to TypeScript**: Adds static type checking with TypeScript

**Angular Migration Templates**

* **Angular 12 to 15**: Handles breaking changes and new API adoptions
* **AngularJS to Angular**: Complete framework migration with modern patterns
* **Angular Forms migration**: Updates to reactive forms and validation patterns
* **Angular Router updates**: Migrates routing configurations and guards

**Vue Migration Templates**

* **Vue 2 to Vue 3**: Comprehensive migration including Composition API
* **Options API to Composition API**: Modernizes component structure
* **Vuex to Pinia**: State management migration to modern patterns
* **Vue Router updates**: Updates routing for Vue 3 compatibility

#### Backend and language migrations

**Java migration templates**

* **Java 8 to 11**: Updates language features and deprecated APIs
* **Java 11 to 17**: Adopts new language features and performance improvements
* **Java 17 to 21**: Latest language features and virtual threads
* **Spring Boot 2.x to 3.x**: Framework upgrade with configuration updates

**Node.js migration templates**

* **Node.js 14 to 18**: Runtime updates and new API adoption
* **Node.js 16 to 20**: Performance improvements and feature updates
* **Express.js upgrades**: Framework version migrations with middleware updates
* **CommonJS to ES modules**: Module system modernization

**Python migration templates**

* **Python 2.7 to 3.x**: Complete language migration with syntax updates
* **Django upgrades**: Framework version migrations with ORM updates
* **Flask modernization**: Updates to modern Flask patterns and features
* **Async/Await migration**: Converts callback patterns to modern async syntax

#### Infrastructure and platform migrations

**Cloud platform migrations**

* **File storage migration**: Migration to AWS, Azure, or Google Cloud
* **Docker Optimization**: Container best practices and multi-stage builds
* **CI/CD Platform Migration**: Jenkins to GitHub Actions, Travis to GitLab CI

**Database migration templates**

* **MySQL 5.7 to 8.0**: Database version upgrades with compatibility fixes
* **PostgreSQL Upgrades**: Version migrations with feature adoption
* **MongoDB Updates**: NoSQL database version and API migrations

### Migration without a template

#### 1. Migration assessment and planning

Start by describing your migration goals:

```
"We need to migrate our React 16 application to React 18. The application includes:
- 150+ components using class-based patterns
- Legacy Context API implementation
- Deprecated lifecycle methods
- PropTypes for type checking
- We want to adopt React 18 features while maintaining all functionality"
```

**What Runbooks does:**

* Analyzes your entire codebase to understand current patterns
* Identifies all components that need migration
* Maps dependencies and potential breaking changes
* Creates a comprehensive migration plan with risk assessment

#### 2. Compatibility analysis

Runbooks performs deep compatibility analysis:

* **Breaking changes**: Identifies APIs that have changed or been removed
* **Dependency updates**: Analyzes third-party library compatibility
* **Feature adoption**: Recommends new features to adopt during migration
* **Risk assessment**: Evaluates potential issues and mitigation strategies

#### 3. Incremental migration strategy

The AI creates a step-by-step migration plan:

* **Infrastructure Updates**: Update build tools, dependencies, and configuration
* **Core API Migration**: Update fundamental framework APIs and patterns
* **Component Migration**: Convert components in dependency order
* **Feature Enhancement**: Adopt new framework features and improvements
* **Testing and Validation**: Comprehensive testing at each stage

#### 4. Automated implementation

Runbooks executes migration systematically:

* Updates one component or module at a time
* Maintains functionality throughout the process
* Runs tests after each change to ensure stability
* Creates detailed pull requests explaining each migration step

### Real-world migration examples

#### Example 1: React Class to Hooks Migration

**Before Migration:**

```javascript
class UserProfile extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      user: null,
      loading: true,
      error: null
    };
  }

  async componentDidMount() {
    try {
      const user = await api.getUser(this.props.userId);
      this.setState({ user, loading: false });
    } catch (error) {
      this.setState({ error, loading: false });
    }
  }

  componentDidUpdate(prevProps) {
    if (prevProps.userId !== this.props.userId) {
      this.fetchUser();
    }
  }

  fetchUser = async () => {
    this.setState({ loading: true });
    try {
      const user = await api.getUser(this.props.userId);
      this.setState({ user, loading: false });
    } catch (error) {
      this.setState({ error, loading: false });
    }
  }

  render() {
    const { user, loading, error } = this.state;
    if (loading) return <LoadingSpinner />;
    if (error) return <ErrorMessage error={error} />;
    return <UserDetails user={user} />;
  }
}
```

**After Runbooks Migration:**

```javascript
import { useState, useEffect, useCallback } from 'react';

const UserProfile = ({ userId }) => {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  const fetchUser = useCallback(async () => {
    setLoading(true);
    setError(null);
    try {
      const userData = await api.getUser(userId);
      setUser(userData);
    } catch (err) {
      setError(err);
    } finally {
      setLoading(false);
    }
  }, [userId]);

  useEffect(() => {
    fetchUser();
  }, [fetchUser]);

  if (loading) return <LoadingSpinner />;
  if (error) return <ErrorMessage error={error} />;
  return <UserDetails user={user} />;
};

export default UserProfile;
```

#### Example 2: Python 2 to Python 3 Migration

**Before Migration:**

```python
# Python 2 syntax and patterns
import urllib2
import ConfigParser

class DataProcessor:
    def __init__(self, config_file):
        self.config = ConfigParser.ConfigParser()
        self.config.read(config_file)

    def fetch_data(self, url):
        response = urllib2.urlopen(url)
        data = response.read()
        return unicode(data, 'utf-8')

    def process_items(self, items):
        for item in items:
            print "Processing:", item
            yield item.upper()

    def get_keys(self, data_dict):
        return data_dict.keys()
```

**After Runbooks Migration:**

```python
# Python 3 syntax and patterns
import urllib.request
import configparser

class DataProcessor:
    def __init__(self, config_file):
        self.config = configparser.ConfigParser()
        self.config.read(config_file)

    def fetch_data(self, url):
        with urllib.request.urlopen(url) as response:
            data = response.read()
            return data.decode('utf-8')

    def process_items(self, items):
        for item in items:
            print("Processing:", item)
            yield item.upper()

    def get_keys(self, data_dict):
        return list(data_dict.keys())
```

#### Example 3: Angular 12 to 15 Migration

**Before Migration:**

```typescript
// Angular 12 patterns
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';

@Component({
  selector: 'app-user-form',
  template: `
    <form [formGroup]="userForm" (ngSubmit)="onSubmit()">
      <input formControlName="name" placeholder="Name">
      <input formControlName="email" placeholder="Email">
      <button type="submit">Submit</button>
    </form>
  `
})
export class UserFormComponent implements OnInit {
  userForm: FormGroup;

  constructor(private fb: FormBuilder) {}

  ngOnInit() {
    this.userForm = this.fb.group({
      name: ['', Validators.required],
      email: ['', [Validators.required, Validators.email]]
    });
  }

  onSubmit() {
    if (this.userForm.valid) {
      console.log(this.userForm.value);
    }
  }
}
```

**After Runbooks Migration:**

```typescript
// Angular 15 with modern patterns
import { Component, inject } from '@angular/core';
import { FormBuilder, Validators, ReactiveFormsModule } from '@angular/forms';
import { CommonModule } from '@angular/common';

@Component({
  selector: 'app-user-form',
  standalone: true,
  imports: [CommonModule, ReactiveFormsModule],
  template: `
    <form [formGroup]="userForm" (ngSubmit)="onSubmit()">
      <input formControlName="name" placeholder="Name">
      <input formControlName="email" placeholder="Email">
      <button type="submit" [disabled]="userForm.invalid">Submit</button>
    </form>
  `
})
export class UserFormComponent {
  private fb = inject(FormBuilder);

  userForm = this.fb.nonNullable.group({
    name: ['', Validators.required],
    email: ['', [Validators.required, Validators.email]]
  });

  onSubmit() {
    if (this.userForm.valid) {
      const formValue = this.userForm.getRawValue();
      console.log(formValue);
    }
  }
}
```

### Advanced migration scenarios

#### Monolith to microservices migration

**Large-scale architecture migration:**

```
"Migrate our monolithic application to microservices architecture:
- Extract user management into a separate service
- Create API gateways for service communication
- Implement distributed tracing and monitoring
- Maintain data consistency across services"
```

**Migration strategy:**

1. **Service boundary analysis**: Identify logical service boundaries
2. **API design**: Create clean interfaces between services
3. **Data migration**: Handle database splitting and consistency
4. **Infrastructure setup**: Container orchestration and service discovery
5. **Gradual cutover**: Incremental migration with feature flags

#### Cross-platform migration

**Technology stack migration:**

```
"Migrate our .NET Framework application to .NET Core for cloud deployment:
- Update framework-specific APIs to .NET Core equivalents
- Migrate Entity Framework to EF Core
- Update deployment configuration for containerization
- Maintain Windows compatibility while adding Linux support"
```

**Comprehensive approach:**

1. **Compatibility assessment**: Identify .NET Core compatibility issues
2. **API migration**: Update framework-specific code
3. **Configuration updates**: Modernize configuration patterns
4. **Testing strategy**: Ensure cross-platform compatibility
5. **Deployment modernization**: Container and cloud-ready deployment

#### Legacy system modernization

**Complete technology refresh:**

```
"Modernize our legacy jQuery application to React:
- Convert jQuery DOM manipulation to React components
- Replace Ajax calls with modern fetch API and state management
- Implement modern routing and navigation
- Add TypeScript for type safety"
```

**Modernization steps:**

1. **Component identification**: Map jQuery code to React components
2. **State management**: Implement modern state patterns
3. **API integration**: Replace jQuery Ajax with modern patterns
4. **UI modernization**: Update styling and user experience
5. **Testing implementation**: Add comprehensive test coverage

***

### See also

* [Code refactoring](/runbooks/concepts/use-cases/code-refactoring.md)
* [Product backlog](/runbooks/concepts/use-cases/product-backlog.md)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.aviator.co/runbooks/concepts/use-cases/code-migrations.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
