Sending thousands of sympathy cards with robots

July 20, 2025

1. Project overview

  • Client need – The Client wanted to send heartfelt sympathy cards to customers after a home-care visit. Doing this manually was labor-intensive and needed to be scalable to thousands of cards per month.
  • Solution – We built a fully automated system that reads job data from the appointment management system, constructs a personalized card order and uses the Handwrytten API to send the card. Once Handwrytten receives a card order through the API, their robots hand write a card and mail it to the recipient. All infrastructure is created through AWS CDK and runs serverlessly, costing the Client less than 10 USD per month in infrastructure.

2. Challenge

  • Manual process – Staff spent significant time writing sympathy cards by hand. Automating the workflow with Handwrytten's robots has replaced thousands of cards the team would have written manually, saving staff members thousands of minutes since launch, while an automatic deduplication step ensures no customer receives a card twice.
  • Personalization at scale – Each sympathy card had to include the customer’s name, address and a message from the appointment management system’s “Sympathy Card” custom field, and the return address needed to be dynamically set depending on the office across several states.

3. How it works

  • Infrastructure – An AWS CDK stack sets up the entire solution. It deploys a Rust‑based Lambda function using the cargo-lambda-cdk construct, a DynamoDB table with TTL and a global secondary index for storing processed job IDs, a Node.js Lambda for de-duplicating jobs, and EventBridge rules that trigger the workflow on configurable schedules.
  • Event scheduling – Separate EventBridge rules run the integration Lambda on different frequencies for each state. Custom event payloads carry the appointment management system instance name and client credentials for each office.
  • Workflow – When triggered, the Rust Lambda:
    1. Reads the appointment management system API credentials from the event and retrieves an OAuth access token.
    2. Fetches a list of jobs filtered by status (“Invoiced, Paid in Full”) and a configurable date range.
    3. Sends all job IDs to a separate de-duplication Lambda; it returns only unprocessed job IDs.
    4. For each job, it gets the full job data and checks for a “Sympathy Card” message; if absent, the job is skipped.
    5. Looks up the customer, builds a delivery address and return address (choosing the correct office across several states) and constructs an order payload for Handwrytten.
    6. Sends the order to the Handwrytten API; occasionally sends a sample order for quality control if enabled.
    7. Saves the processed job ID and order metadata to DynamoDB, setting a 45‑day TTL to avoid long‑term storage.
    8. Sends a Slack notification to staff to confirm a card was queued (we set this behind a feature flag, not yet enabled in production).
    9. Pauses for two seconds between orders to respect external API rate limits and verifies that jobs with a sympathy message have been recorded in DynamoDB.

4. Technologies used

  • AWS Cloud Development Kit (CDK) – Defines the stack, EventBridge schedules and DynamoDB table in TypeScript.
  • Rust & Tokio – Implements the main Lambda handler, uses async requests to the appointment management system and Handwrytten, and performs concurrency safely.
  • Node.js – A secondary Lambda performs job de-duplication.
  • DynamoDB – Stores processed job IDs with TTL; includes a global secondary index for efficient expiry management.
  • EventBridge – Schedules the workflow; custom cron expressions set the frequency for each region.
  • Slack integration – Sends notifications when a card order is queued (feature flag currently disabled).
  • Handwrytten API – Accepts the order payload constructed from job and customer details and returns a confirmation order ID.

5. Benefits for customers

  • Personal touch, automated – Customers receive sincere sympathy cards automatically, with a message pulled from the appointment management system job and a return address appropriate to the local office.
  • Reliability – The system tracks processed jobs in DynamoDB to ensure no duplicates and de-duplicates job lists with a dedicated Lambda.
  • Quality control – We used a random number generator to periodically send a sample card (based on a real order) to an internal address for verification.
  • Scalability & cost-effectiveness – Running on serverless AWS services means it scales automatically and incurs costs only when processing events.
  • Timely communication – EventBridge schedules can be tuned per region, ensuring cards are queued promptly after invoicing.

6. Outcome and next steps

  • The automated system delivers sympathy cards to customers without manual effort, creating memorable experiences and strengthening relationships. It has saved the Client's staff dozens of hours since launch and will continue to accrue time savings for the Client's company the longer it's in operation.
  • Future enhancements could include supporting additional offices, adding personalization options (fonts, handwritten signatures), or extending the workflow to other customer touchpoints.