Quick Start Guide

This guide walks you through creating your first Da Vinci application.

Prerequisites

Before starting, ensure you have:

  • Python 3.11+ installed (Python 3.12+ required for CDK)

  • Docker installed and running (required for Lambda function packaging)

  • AWS account with appropriate permissions (DynamoDB, Lambda, CloudFormation)

  • AWS credentials configured (aws configure)

  • AWS CDK CLI installed (npm install -g aws-cdk)

  • Da Vinci packages installed (see Installation)

Creating Your First Application

Step 1: Define a DynamoDB Table

Create a file called tables.py to define your DynamoDB tables:

from da_vinci.core.orm.table_object import (
    TableObject,
    TableObjectAttribute,
    TableObjectAttributeType,
)

class UserTable(TableObject):
    """User table for storing user information"""

    table_name = "users"

    partition_key_attribute = TableObjectAttribute(
        name="user_id",
        attribute_type=TableObjectAttributeType.STRING,
        description="Unique user identifier",
    )

    attributes = [
        TableObjectAttribute(
            name="email",
            attribute_type=TableObjectAttributeType.STRING,
            description="User email address",
        ),
        TableObjectAttribute(
            name="name",
            attribute_type=TableObjectAttributeType.STRING,
            description="User display name",
        ),
        TableObjectAttribute(
            name="created_at",
            attribute_type=TableObjectAttributeType.DATETIME,
            description="When the user was created",
        ),
    ]

Step 2: Create Application Logic

Create a file called user_service.py for your business logic:

from datetime import UTC, datetime
from da_vinci.core.orm.client import TableClient
from tables import UserTable

class UserService:
    def __init__(self):
        self.table_client = TableClient(UserTable)

    def create_user(self, user_id: str, email: str, name: str):
        """Create a new user"""
        user = UserTable(
            user_id=user_id,
            email=email,
            name=name,
            created_at=datetime.now(UTC),
        )
        self.table_client.put(user)
        return user

    def get_user(self, user_id: str):
        """Retrieve a user by ID"""
        return self.table_client.get(user_id)

    def list_users(self):
        """List all users"""
        return list(self.table_client.scan())

Step 3: Create Table Stack

Create a file called table_stack.py for your DynamoDB table stack:

from constructs import Construct
from da_vinci_cdk.stack import Stack
from da_vinci_cdk.constructs.dynamodb import DynamoDBTable
from tables import UserTable

class UserTableStack(Stack):
    """Stack that provisions the User DynamoDB Table"""

    def __init__(
        self,
        app_name: str,
        deployment_id: str,
        scope: Construct,
        stack_name: str
    ) -> None:
        super().__init__(
            app_name=app_name,
            deployment_id=deployment_id,
            scope=scope,
            stack_name=stack_name,
        )

        self.table = DynamoDBTable.from_orm_table_object(
            table_object=UserTable,
            scope=self,
        )

Step 4: Deploy Infrastructure with CDK

Create a file called app.py for your CDK infrastructure:

from os.path import dirname, abspath
from da_vinci_cdk.application import Application
from table_stack import UserTableStack

# Create application
app = Application(
    app_name="my-app",
    deployment_id="dev",
    app_entry=abspath(dirname(__file__)),
)

# Add table stack to application
app.add_uninitialized_stack(UserTableStack)

# Synthesize CDK stacks
app.synth()

Note

Naming Requirements: app_name and deployment_id must use only alphanumeric characters and hyphens. They must start with a letter. Do not use underscores, as CloudFormation stack names follow the pattern /^[A-Za-z][A-Za-z0-9-]*$/.

Step 5: Deploy to AWS

Deploy your application to AWS using the CDK CLI:

# Bootstrap CDK (first time only)
cdk bootstrap

# Deploy the application
cdk deploy --all

Step 6: Use Your Application

Now you can use your application:

from user_service import UserService

# Create service instance
service = UserService()

# Create a user
user = service.create_user(
    user_id="user-123",
    email="alice@example.com",
    name="Alice Smith"
)

# Retrieve the user
retrieved_user = service.get_user("user-123")
print(f"User: {retrieved_user.name} ({retrieved_user.email})")

# List all users
users = service.list_users()
for user in users:
    print(f"- {user.name}")

Summary

In these steps, you:

  1. Defined a DynamoDB table using Da Vinci’s table object system

  2. Created business logic using the table client for CRUD operations

  3. Deployed infrastructure automatically from your table definitions

  4. Used your application with type-safe table objects

Key Concepts

Table Objects

Table objects define both your data model and drive infrastructure generation. They provide type safety and eliminate boilerplate for DynamoDB operations.

Table Client

The table client provides methods for interacting with DynamoDB tables: put(), get(), scan(), query(), and more.

Application

The CDK Application construct manages your infrastructure deployment, automatically creating resources from your table definitions.

Next Steps

Now that you’ve built your first application, explore:

Common Patterns

Adding Indexes

class UserTable(TableObject):
    table_name = "users"
    partition_key_attribute = "user_id"

    # Add a GSI for querying by email
    global_secondary_indexes = [
        {
            "index_name": "email_index",
            "partition_key": "email",
        }
    ]

Querying with Indexes

# Query by email using GSI
users = table_client.query(
    index_name="email_index",
    partition_key_value="alice@example.com"
)

Using Scan Filters

from da_vinci.core.orm.client import TableScanDefinition

# Scan with filter
scan_def = TableScanDefinition(UserTable)
scan_def.add("email", "contains", "@example.com")

users = table_client.scan(scan_definition=scan_def)

Troubleshooting

Table Not Found

Ensure you’ve deployed your infrastructure with cdk deploy --all and that your AWS credentials are configured correctly.

Import Errors

Make sure both da-vinci and da-vinci-cdk are installed in your environment.

Permission Errors

Ensure your AWS credentials have permissions to create DynamoDB tables and other required resources.