1"use strict";(self.webpackChunkdocs_formkiq_com=self.webpackChunkdocs_formkiq_com||[]).push([[4384],{20967:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>c,contentTitle:()=>a,default:()=>h,frontMatter:()=>o,metadata:()=>i,toc:()=>d});const i=JSON.parse('{"id":"platform/backup_and_recovery","title":"Backup and Recovery","description":"Overview","source":"@site/docs/platform/backup_and_recovery.md","sourceDirName":"platform","slug":"/platform/backup_and_recovery","permalink":"/docs/platform/backup_and_recovery","draft":false,"unlisted":false,"editUrl":"https://github.com/formkiq/docs.formkiq.com/tree/main/docs/platform/backup_and_recovery.md","tags":[],"version":"current","sidebarPosition":8,"frontMatter":{"sidebar_position":8,"toc_min_heading_level":2,"toc_max_heading_level":2},"sidebar":"tutorialSidebar","previous":{"title":"Updates, Upgrades, and Rollbacks","permalink":"/docs/platform/updates_upgrades_and_rollbacks"},"next":{"title":"Migration and Data Import","permalink":"/docs/platform/migration-and-data-import"}}');var t=r(74848),s=r(28453);const o={sidebar_position:8,toc_min_heading_level:2,toc_max_heading_level:2},a="Backup and Recovery",c={},d=[{value:"Overview",id:"overview",level:2},{value:"Core System Components",id:"core-system-components",level:2},{value:"Shared Responsibility",id:"shared-responsibility",level:2},{value:"Automated Backup Capabilities",id:"automated-backup-capabilities",level:2},{value:"DynamoDB Point-in-Time Recovery",id:"dynamodb-point-in-time-recovery",level:3},{value:"S3 Object Versioning",id:"s3-object-versioning",level:3},{value:"OpenSearch Automated Snapshots",id:"opensearch-automated-snapshots",level:3},{value:"AWS Backup",id:"aws-backup",level:2},{value:"AWS Backup Integration",id:"aws-backup-integration",level:3},{value:"Additional Backup Options",id:"additional-backup-options",level:2},{value:"On-Demand Backups",id:"on-demand-backups",level:3},{value:"Document Metadata Export",id:"document-metadata-export",level:3},{value:"Cognito and Identity Configuration Export",id:"cognito-and-identity-configuration-export",level:3},{value:"CloudFormation Stack Backup",id:"cloudformation-stack-backup",level:3},{value:"Recovery Procedures",id:"recovery-procedures",level:2},{value:"Recovery Decision Guide",id:"recovery-decision-guide",level:3},{value:"Document Restore and S3 Recovery",id:"document-restore-and-s3-recovery",level:3},{value:"DynamoDB Point-in-Time Recovery",id:"dynamodb-point-in-time-recovery-1",level:3},{value:"OpenSearch Index Recovery",id:"opensearch-index-recovery",level:3},{value:"Complete System Recovery",id:"complete-system-recovery",level:3},{value:"Disaster Recovery Strategies",id:"disaster-recovery-strategies",level:2},{value:"Cross-Region Replication",id:"cross-region-replication",level:3},{value:"DynamoDB Global Tables",id:"dynamodb-global-tables",level:3},{value:"Backup Strategy Tiers",id:"backup-strategy-tiers",level:3},{value:"Testing and Validation",id:"testing-and-validation",level:2},{value:"Backup Monitoring and Maintenance",id:"backup-monitoring-and-maintenance",level:2},{value:"Compliance and Retention",id:"compliance-and-retention",level:2},{value:"Cost Optimization",id:"cost-optimization",level:2},{value:"Additional Considerations",id:"additional-considerations",level:2},{value:"Multi-Tenant Environment Backups",id:"multi-tenant-environment-backups",level:3},{value:"Automation and Integration",id:"automation-and-integration",level:3},{value:"Additional Resources",id:"additional-resources",level:2}];function l(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",li:"li",ol:"ol",p:"p",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,s.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.header,{children:(0,t.jsx)(n.h1,{id:"backup-and-recovery",children:"Backup and Recovery"})}),"\n",(0,t.jsx)(n.h2,{id:"overview",children:"Overview"}),"\n",(0,t.jsx)(n.p,{children:"Backup and recovery planning for FormKiQ should cover document content, document metadata, configuration, identity, search indexes, logs, and any external systems connected to your workflows."}),"\n",(0,t.jsx)(n.p,{children:"FormKiQ includes important AWS-native recovery controls, such as DynamoDB Point-in-Time Recovery and S3 bucket versioning, but customers remain responsible for defining recovery objectives, retention policies, backup monitoring, restore testing, and disaster recovery architecture."}),"\n",(0,t.jsx)(n.p,{children:"Your plan should define:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Recovery Time Objective (RTO): how quickly service must be restored"}),"\n",(0,t.jsx)(n.li,{children:"Recovery Point Objective (RPO): how much data loss is acceptable"}),"\n",(0,t.jsx)(n.li,{children:"Retention requirements for documents, metadata, logs, and backups"}),"\n",(0,t.jsx)(n.li,{children:"Region, account, and data residency requirements"}),"\n",(0,t.jsx)(n.li,{children:"Recovery ownership and approval process"}),"\n",(0,t.jsx)(n.li,{children:"Testing cadence for restore procedures"}),"\n"]}),"\n",(0,t.jsx)(n.admonition,{type:"warning",children:(0,t.jsx)(n.p,{children:"Backups are only useful if restore procedures are known and tested. Validate recovery in a non-production environment before relying on a process for production."})}),"\n",(0,t.jsx)(n.h2,{id:"core-system-components",children:"Core System Components"}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Component"}),(0,t.jsx)(n.th,{children:"AWS service"}),(0,t.jsx)(n.th,{children:"Default or common protection"}),(0,t.jsx)(n.th,{children:"Customer planning required"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Document content"}),(0,t.jsx)(n.td,{children:"Amazon S3"}),(0,t.jsx)(n.td,{children:"S3 versioning in standard FormKiQ document buckets."}),(0,t.jsx)(n.td,{children:"Lifecycle rules, retention, replication, object lock, purge policy, recovery testing."})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Document metadata"}),(0,t.jsx)(n.td,{children:"Amazon DynamoDB"}),(0,t.jsx)(n.td,{children:"Point-in-Time Recovery for critical tables, except cache tables."}),(0,t.jsx)(n.td,{children:"Restore process, table cutover or data repair plan, long-term exports if needed."})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Site and application configuration"}),(0,t.jsx)(n.td,{children:"DynamoDB, CloudFormation, parameters"}),(0,t.jsx)(n.td,{children:"Some configuration stored in FormKiQ tables and stack configuration."}),(0,t.jsx)(n.td,{children:"Stack template, parameters, outputs, module configuration, and change history exports."})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"User authentication"}),(0,t.jsx)(n.td,{children:"Amazon Cognito or external IdP"}
1),(0,t.jsx)(n.td,{children:"Cognito and IdP configuration managed outside document storage."}),(0,t.jsx)(n.td,{children:"User pool/app client/group export, SSO metadata backup, IdP recovery process."})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Search indexes"}),(0,t.jsx)(n.td,{children:"Typesense or Amazon OpenSearch when enabled"}),(0,t.jsx)(n.td,{children:"Backend-specific index durability; OpenSearch snapshots where configured."}),(0,t.jsx)(n.td,{children:"Snapshot, restore, or reindex plan."})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Document processing state"}),(0,t.jsx)(n.td,{children:"DynamoDB, queues, Lambda, logs"}),(0,t.jsx)(n.td,{children:"Operational records in FormKiQ tables and CloudWatch logs."}),(0,t.jsx)(n.td,{children:"Recovery expectations for in-flight workflows and failed actions."})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Observability and audit"}),(0,t.jsx)(n.td,{children:"CloudWatch, CloudTrail, FormKiQ activity records"}),(0,t.jsx)(n.td,{children:"Logs and events depend on customer retention settings."}),(0,t.jsx)(n.td,{children:"Log retention, export, audit review, and incident evidence requirements."})]})]})]}),"\n",(0,t.jsx)(n.h2,{id:"shared-responsibility",children:"Shared Responsibility"}),"\n",(0,t.jsx)(n.p,{children:"FormKiQ deploys into your AWS account. That gives you control over data residency, backup retention, encryption, monitoring, and recovery procedures, but it also means your operations team should validate those controls."}),"\n",(0,t.jsx)(n.p,{children:"FormKiQ provides or configures:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"DynamoDB Point-in-Time Recovery for critical tables, excluding cache tables"}),"\n",(0,t.jsx)(n.li,{children:"S3 versioning for document storage buckets in standard deployments"}),"\n",(0,t.jsx)(n.li,{children:"CloudFormation-managed infrastructure"}),"\n",(0,t.jsx)(n.li,{children:"API operations for document restore, document versions, OpenSearch snapshots, and reindexing where supported"}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"Customers should define:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Backup retention and legal hold requirements"}),"\n",(0,t.jsx)(n.li,{children:"AWS Backup usage, if required"}),"\n",(0,t.jsx)(n.li,{children:"Cross-region or cross-account backup copies"}),"\n",(0,t.jsx)(n.li,{children:"OpenSearch snapshot retention"}),"\n",(0,t.jsx)(n.li,{children:"Restore testing cadence"}),"\n",(0,t.jsx)(n.li,{children:"Incident response and recovery ownership"}),"\n",(0,t.jsx)(n.li,{children:"Procedures for external identity providers and downstream integrations"}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"automated-backup-capabilities",children:"Automated Backup Capabilities"}),"\n",(0,t.jsx)(n.h3,{id:"dynamodb-point-in-time-recovery",children:"DynamoDB Point-in-Time Recovery"}),"\n",(0,t.jsx)(n.p,{children:"FormKiQ configures Point-in-Time Recovery (PITR) for critical DynamoDB tables, excluding cache tables. PITR allows a table to be restored to a new table at a selected point within the recovery window."}),"\n",(0,t.jsx)(n.p,{children:"PITR is useful for:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Accidental metadata deletion"}),"\n",(0,t.jsx)(n.li,{children:"Bad application writes"}),"\n",(0,t.jsx)(n.li,{children:"Failed imports or migrations"}),"\n",(0,t.jsx)(n.li,{children:"Operational recovery within the 35-day PITR window"}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"Important limitations:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"PITR restores to a new DynamoDB table. It does not overwrite the live table automatically."}),"\n",(0,t.jsx)(n.li,{children:"Restoring a FormKiQ table requires a controlled data repair, replacement, or cutover plan."}),"\n",(0,t.jsx)(n.li,{children:"Related data across multiple tables may need to be restored to the same recovery point."}),"\n",(0,t.jsx)(n.li,{children:"PITR does not restore S3 object content, OpenSearch indexes, Cognito users, or external systems."}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"Verify PITR:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"aws dynamodb describe-continuous-backups \\\n --table-name formkiq-documents-table-name\n"})}),"\n",(0,t.jsx)(n.h3,{id:"s3-object-versioning",children:"S3 Object Versioning"}),"\n",(0,t.jsx)(n.p,{children:"FormKiQ document content is stored in Amazon S3. S3 versioning helps protect against accidental overwrite or deleti
1on by retaining previous object versions and delete markers."}),"\n",(0,t.jsx)(n.p,{children:"S3 versioning is useful for:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Recovering previous document content"}),"\n",(0,t.jsx)(n.li,{children:"Recovering objects hidden by delete markers"}),"\n",(0,t.jsx)(n.li,{children:"Investigating accidental overwrite events"}),"\n",(0,t.jsx)(n.li,{children:"Supporting rollback and audit scenarios"}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"Important limitations:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"S3 versioning does not replace retention policy, legal hold, or object lock requirements."}),"\n",(0,t.jsx)(n.li,{children:"Lifecycle rules can expire old versions if configured to do so."}),"\n",(0,t.jsx)(n.li,{children:"Permanent purge operations and retention policies may affect recoverability."}),"\n",(0,t.jsx)(n.li,{children:"Metadata in DynamoDB and content in S3 may need to be reconciled together."}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"Verify bucket versioning:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"aws s3api get-bucket-versioning \\\n --bucket your-formkiq-document-bucket\n"})}),"\n",(0,t.jsx)(n.h3,{id:"opensearch-automated-snapshots",children:"OpenSearch Automated Snapshots"}),"\n",(0,t.jsx)(n.p,{children:"Enhanced full-text search deployments may use Amazon OpenSearch Service. OpenSearch recovery should be planned separately from DynamoDB and S3."}),"\n",(0,t.jsx)(n.p,{children:"OpenSearch snapshots are useful for:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Restoring search indexes after index corruption"}),"\n",(0,t.jsx)(n.li,{children:"Recovering from accidental index deletion"}),"\n",(0,t.jsx)(n.li,{children:"Preserving search state before major search configuration changes"}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"Important limitations:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Search indexes are derived data. In some cases, reindexing from source documents is safer than restoring an old index."}),"\n",(0,t.jsx)(n.li,{children:"Snapshot availability and retention depend on the OpenSearch configuration."}),"\n",(0,t.jsx)(n.li,{children:"Restoring search does not restore source document metadata or content."}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"Related operations:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"/docs/api-reference/add-open-search-snapshot",children:"Add OpenSearch Snapshot"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"/docs/api-reference/get-open-search-snapshots",children:"Get OpenSearch Snapshots"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"/docs/api-reference/add-open-search-restore-snapshot",children:"Restore OpenSearch Snapshot"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"/docs/api-reference/add-reindex-document",children:"Reindex Document"})}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"aws-backup",children:"AWS Backup"}),"\n",(0,t.jsx)(n.p,{children:"AWS Backup can centralize backup policy management across AWS services used by FormKiQ. It can be useful for enterprise governance, cross-account backup copies, retention enforcement, audit reporting, and Backup Vault Lock."}),"\n",(0,t.jsx)(n.p,{children:"AWS Backup does not replace DynamoDB PITR for operational point-in-time recovery. Keep PITR enabled where FormKiQ configures it."}),"\n",(0,t.jsx)(n.h3,{id:"aws-backup-integration",children:"AWS Backup Integration"}),"\n",(0,t.jsx)(n.p,{children:"Use AWS Backup when you need:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Centralized backup plans"}),"\n",(0,t.jsx)(n.li,{children:"Cross-region or cross-account backup copies"}),"\n",(0,t.jsx)(n.li,{children:"Backup vault encryption and access policy controls"}),"\n",(0,t.jsx)(n.li,{children:"Backup Vault Lock for immutability"}),"\n",(0,t.jsx)(n.li,{children:"Compliance reporting across AWS accounts"}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"Plan AWS Backup around resources such as:"}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"FormKiQ area"}),(0,t.jsx)(n.th,{children:"AWS Backup consideration"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"DynamoDB tables"}),(0,t.jsx)(n.td,{children:"Use backup plans for scheduled recovery points beyond PITR needs."})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"S3 buckets"}),(0,t.jsx)(n.td,{children:"Use AWS Backup for policy-based S3 backups if your compliance model requires it."})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"OpenSearch indexes"}),(0,t.jsx)(n.td,{children:"Manage OpenSearch snapshots separately. Do not assume AWS Backup replaces OpenSearch snapshot planning."})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"CloudFormation configuration"}),(0,t.jsx)(n.td,{children:"Export templates, parameters, and outputs separately."})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Cognito and IdP c
1onfiguration"}),(0,t.jsx)(n.td,{children:"Export or document separately; AWS Backup does not provide a full identity recovery story."})]})]})]}),"\n",(0,t.jsx)(n.p,{children:"Example AWS Backup plan shape:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-json",children:'{\n "BackupPlan": {\n "BackupPlanName": "FormKiQ-Daily-Backup",\n "Rules": [\n {\n "RuleName": "DailyBackups",\n "TargetBackupVault": "FormKiQ-Vault",\n "ScheduleExpression": "cron(0 5 * * ? *)",\n "StartWindowMinutes": 60,\n "CompletionWindowMinutes": 180,\n "Lifecycle": {\n "DeleteAfterDays": 35\n },\n "RecoveryPointTags": {\n "Application": "FormKiQ"\n }\n }\n ]\n }\n}\n'})}),"\n",(0,t.jsx)(n.h2,{id:"additional-backup-options",children:"Additional Backup Options"}),"\n",(0,t.jsx)(n.h3,{id:"on-demand-backups",children:"On-Demand Backups"}),"\n",(0,t.jsx)(n.p,{children:"Use on-demand DynamoDB backups for stable recovery points that must persist beyond the PITR window."}),"\n",(0,t.jsx)(n.p,{children:"Best for:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Pre-upgrade safeguards"}),"\n",(0,t.jsx)(n.li,{children:"Migration checkpoints"}),"\n",(0,t.jsx)(n.li,{children:"Long-term retention"}),"\n",(0,t.jsx)(n.li,{children:"Compliance evidence"}),"\n",(0,t.jsx)(n.li,{children:"Point-in-time snapshots before high-risk changes"}),"\n"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"aws dynamodb create-backup \\\n --table-name formkiq-documents-table-name \\\n --backup-name PreMigrationBackup\n"})}),"\n",(0,t.jsx)(n.h3,{id:"document-metadata-export",children:"Document Metadata Export"}),"\n",(0,t.jsx)(n.p,{children:"DynamoDB export to S3 can support long-term archival, analytics, c
1ompliance reporting, and migration workflows."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:'aws dynamodb export-table-to-point-in-time \\\n --table-arn arn:aws:dynamodb:us-east-1:123456789012:table/formkiq-documents-table-name \\\n --s3-bucket your-backup-bucket \\\n --s3-prefix document-metadata-backup \\\n --export-format DYNAMODB_JSON \\\n --export-time "2026-05-20T12:00:00Z"\n'})}),"\n",(0,t.jsx)(n.p,{children:"Best for:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Extended archival needs"}),"\n",(0,t.jsx)(n.li,{children:"Compliance reporting"}),"\n",(0,t.jsx)(n.li,{children:"Offline analysis"}),"\n",(0,t.jsx)(n.li,{children:"Migration planning"}),"\n",(0,t.jsx)(n.li,{children:"Independent recovery records"}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"cognito-and-identity-configuration-export",children:"Cognito and Identity Configuration Export"}),"\n",(0,t.jsx)(n.p,{children:"If your deployment uses Amazon Cognito, back up more than the user list."}),"\n",(0,t.jsx)(n.p,{children:"Capture:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"User pool ID and configuration"}),"\n",(0,t.jsx)(n.li,{children:"App clients"}),"\n",(0,t.jsx)(n.li,{children:"Groups and group membership"}),"\n",(0,t.jsx)(n.li,{children:"Custom attributes"}),"\n",(0,t.jsx)(n.li,{children:"Hosted UI/domain settings"}),"\n",(0,t.jsx)(n.li,{children:"Lambda triggers"}),"\n",(0,t.jsx)(n.li,{children:"SAML or OIDC identity provider settings"}),"\n",(0,t.jsx)(n.li,{children:"Password and MFA policy settings"}),"\n"]}),"\n",(0,t.jsx)(n.admonition,{type:"note",children:(0,t.jsx)(n.p,{children:"Cognito user exports do not fully preserve password state, MFA enrollment, app client secrets, hosted UI configuration, or all federation settings. Identity recovery should include configuration documentation and a tested identity-provider recovery process."})}),"\n",(0,t.jsx)(n.p,{children:"Example user export:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"aws cognito-idp list-users \\\n --user-pool-id your-user-pool-id \\\n --output json > cognito-users-export.json\n"})}),"\n",(0,t.jsx)(n.h3,{id:"cloudformation-stack-backup",children:"CloudFormation Stack Backup"}),"\n",(0,t.jsx)(n.p,{children:"Export CloudFormation templates, parameters, and outputs before upgrades and on a regular schedule."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"aws cloudformation get-template \\\n --stack-name your-formkiq-stack \\\n --query TemplateBody \\\n --output json > formkiq-template-backup.json\n"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:'aws cloudformation describe-stacks \\\n --stack-name your-formkiq-stack \\\n --query "Stacks[0].{Parameters:Parameters,Outputs:Outputs}" \\\n --output json > formkiq-stack-state-backup.json\n'})}),"\n",(0,t.jsx)(n.h2,{id:"recovery-procedures",children:"Recovery Procedures"}),"\n",(0,t.jsx)(n.h3,{id:"recovery-decision-guide",children:"Recovery Decision Guide"}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Scenario"}),(0,t.jsx)(n.th,{children:"First recovery path"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"A user soft-deleted a document"}),(0,t.jsx)(n.td,{children:"Use FormKiQ document restore."})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"A document was overwritten"}),(0,t.jsx)(n.td,{children:"Restore the previous S3 object version and reconcile metadata if needed."})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"A document was purged"}),(0,t.jsx)(n.td,{children:"Review backups, audit logs, retention controls, and legal/compliance requirements. Purge is intended to remove content from active storage."})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Metadata was corrupted"}),(0,t.jsx)(n.td,{children:"Use DynamoDB PITR to restore to a new table, then repair or migrate affected records."})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Search results are wrong"}),(0,t.jsx)(n.td,{children:"Reindex affected documents or restore OpenSearch snapshot if required."})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"User access is broken"}),(0,t.jsx)(n.td,{children:"Restore or reconfigure Cognito, SSO, groups, app clients, or API auth settings."})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Stack configuration was changed incorrectly"}),(0,t.jsx)(n.td,{children:"Reapply previous CloudFormation parameters or template."})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Full environment is unavailable"}),(0,t.jsx)(n.td,{children:"Follow complete environment recovery plan."})]})]})]}),"\n",(0,t.jsx)(n.h3,{id:"document-restore-and-s3-recovery",children:"Document Restore and S3 Recovery"}),"\n",(0,t.jsx)(n.p,{children:"Start with the least disruptive recovery option."}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsxs)(n.li,{children:["If the document was soft-deleted, use FormKiQ restore: ",(0,t.jsx)(n.a,{href:"/docs/api-reference/set-document-restore",children:(0,t.jsx)(n.code,{children:"PUT /documents/{documentId}/restore"})}),"."]}),"\n",(0,t.jsx)(n.li,{children:"If content was overwritten, identify the correct S3 object version."}),"\n",(0,t.jsx)(n.li,{children:"Restore or copy the needed object version."}),"\n",(0,t.jsx)(n.li,{children:"Confirm FormKiQ metadata still points to the expected content."}),"\n",(0,t.jsx)(n.li,{children:"Verify download, search, and document activity records."}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["For purge behavior, review ",(0,t.jsx)(n.a,{href:"/docs/api-reference/purge-document",children:(0,t.jsx)(n.code,{children:"DELETE /documents/{documentId}/purge"})}),". Purge is designed to remove active document content and metadata traces outside audit logs and backups."]}),"\n",(0,t.jsx)(n.h3,{id:"dynamodb-point-in-time-recovery-1",children:"DynamoDB Point-in-Time Recovery"}),"\n",(0,t.jsx)(n.p,{children:"To restore a DynamoDB table:"}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsx)(n.li,{children:"Identify the affected table or tables."}),"\n",(0,t.jsx)(n.li,{children:"Identify the recovery timestamp."}),"\n",(0,t.jsx)(n.li,{children:"Restore the table to a new table."}),"\n",(0,t.jsx)(n.li,{children:"Compare restored records with the live table."}),"\n",(0,t.jsx)(n.li,{children:"Repair affected records, migrate restored data, or plan a controlled cutover."}),"\n",(0,t.jsx)(n.li,{children:"Validate FormKiQ behavior in a test environment before production changes."}),"\n"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:'aws dynamodb restore-table-to-point-in-time \\\n --source-table-name formkiq-documents-table-name \\\n --target-table-name formkiq-documents-restored \\\n --restore-date-time "2026-05-20T12:00:00Z"\n'})}),"\n",(0,t.jsx)(n.admonition,{type:"warning",children:(0,t.jsx)(n.p,{children:"Do not point a production FormKiQ stack at a restored DynamoDB table without a tested cutover plan. FormKiQ data spans tables, S3 content, indexes, queues, and integrations that may need coordinated recovery."})}),"\n",(0,t.jsx)(n.h3,{id:"opensearch-index-recovery",children:"OpenSearch Index Recovery"}),"\n",(0,t.jsx)(n.p,{children:"If enhanced full-text search is installed, choose between reindexing and snapshot restore."}),"\n",(0,t.jsx)(n.p,{children:"Use reindexing when:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Source documents and metadata are healthy"}),"\n",(0,t.jsx)(n.li,{children:"Search results are stale or incomplete"}),"\n",(0,t.jsx)(n.li,{children:"Mappings, schema, or full-text settings changed"}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"Use snapshot restore when:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"The index was deleted or corrupted"}),"\n",(0,t.jsx)(n.li,{children:"Reindexing is too slow for the recovery target"}
1),"\n",(0,t.jsx)(n.li,{children:"A known-good snapshot exists"}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"Related operations:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"/docs/api-reference/get-open-search-snapshots",children:"Get OpenSearch Snapshots"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"/docs/api-reference/add-open-search-restore-snapshot",children:"Restore OpenSearch Snapshot"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"/docs/api-reference/add-reindex-document",children:"Reindex Document"})}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"complete-system-recovery",children:"Complete System Recovery"}),"\n",(0,t.jsx)(n.p,{children:"Full environment recovery usually requires multiple coordinated steps:"}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsx)(n.li,{children:"Redeploy or repair the FormKiQ CloudFormation stack."}),"\n",(0,t.jsx)(n.li,{children:"Restore or validate DynamoDB metadata and configuration."}),"\n",(0,t.jsx)(n.li,{children:"Restore or validate S3 document content."}),"\n",(0,t.jsx)(n.li,{children:"Restore, rebuild, or reindex search backends."}),"\n",(0,t.jsx)(n.li,{children:"Restore Cognito, SSO, custom authorizer, API key, or IAM access paths."}),"\n",(0,t.jsx)(n.li,{children:"Reconfigure domains, certificates, VPC settings, and integrations if needed."}),"\n",(0,t.jsx)(n.li,{children:"Validate API URLs and console access."}),"\n",(0,t.jsx)(n.li,{children:"Run a full functional smoke test."}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"disaster-recovery-strategies",children:"Disaster Recovery Strategies"}),"\n",(0,t.jsx)(n.h3,{id:"cross-region-replication",children:"Cross-Region Replication"}),"\n",(0,t.jsx)(n.p,{children:"Cross-region recovery is an architecture decision, not a simple backup setting. It should be designed and tested before an incident."}),"\n",(0,t.jsx)(n.p,{children:"S3 Cross-Region Replication can help with:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Regional disaster recovery"}),"\n",(0,t.jsx)(n.li,{children:"Data residency or duplicate-region requirements"}),"\n",(0,t.jsx)(n.li,{children:"Protection against regional S3 access disruption"}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"Plan for:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Destination bucket encryption and KMS keys"}),"\n",(0,t.jsx)(n.li,{children:"Replication of delete markers and noncurrent versions"}),"\n",(0,t.jsx)(n.li,{children:"Replication monitoring"}),"\n",(0,t.jsx)(n.li,{children:"Lifecycle policy differences between regions"}),"\n",(0,t.jsx)(n.li,{children:"Application cutover to the recovery region"}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"dynamodb-global-tables",children:"DynamoDB Global Tables"}),"\n",(0,t.jsx)(n.p,{children:"DynamoDB Global Tables may be useful for multi-region architectures, but they should not be treated as a generic backup feature."}),"\n",(0,t.jsx)(n.p,{children:"Use only after validating:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"FormKiQ table design and write patterns"}),"\n",(0,t.jsx)(n.li,{children:"Conflict behavior"}),"\n",(0,t.jsx)(n.li,{children:"Region support"}),"\n",(0,t.jsx)(n.li,{children:"CloudFormation ownership"}),"\n",(0,t.jsx)(n.li,{children:"Recovery runbooks"}),"\n",(0,t.jsx)(n.li,{children:"Cost and operational complexity"}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"For many deployments, PITR, on-demand backups, exports, and tested restore procedures are a better first step than global active-active database replication."}),"\n",(0,t.jsx)(n.h3,{id:"backup-strategy-tiers",children:"Backup Strategy Tiers"}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Tier"}),(0,t.jsx)(n.th,{children:"Strategy"}),(0,t.jsx)(n.th,{children:"Typical use"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Basic"}),(0,t.jsx)(n.td,{children:"DynamoDB PITR, S3 versioning, CloudFormation exports"}),(0,t.jsx)(n.td,{children:"Standard operational recovery in one region."})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Standard"}),(0,t.jsx)(n.td,{children:"Basic plus on-demand backups, metadata exports, restore testing"}),(0,t.jsx)(n.td,{children:"Production environments with formal recovery expectations."})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Enhanced"}),(0,t.jsx)(n.td,{children:"Standard plus AWS Backup, cross-account or cross-region copies, OpenSearch snapshots"}),(0,t.jsx)(n.td,{children:"Regulated or higher availability environments."})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Enterprise"}
1),(0,t.jsx)(n.td,{children:"Enhanced plus tested regional recovery architecture"}),(0,t.jsx)(n.td,{children:"Environments with strict RTO/RPO or region failure requirements."})]})]})]}),"\n",(0,t.jsx)(n.h2,{id:"testing-and-validation",children:"Testing and Validation"}),"\n",(0,t.jsx)(n.p,{children:"Test backup and recovery regularly."}),"\n",(0,t.jsx)(n.p,{children:"Recommended quarterly checks:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Restore a DynamoDB table to a new table and validate sample records."}),"\n",(0,t.jsx)(n.li,{children:"Recover a sample S3 document version and verify checksum or file integrity."}),"\n",(0,t.jsx)(n.li,{children:"Restore a soft-deleted FormKiQ document."}),"\n",(0,t.jsx)(n.li,{children:"Validate OpenSearch snapshot or reindex procedure if enhanced search is installed."}),"\n",(0,t.jsx)(n.li,{children:"Export and review CloudFormation parameters and outputs."}),"\n",(0,t.jsx)(n.li,{children:"Confirm Cognito or SSO recovery documentation is current."}),"\n",(0,t.jsx)(n.li,{children:"Run a complete recovery drill in a non-production environment."}),"\n",(0,t.jsx)(n.li,{children:"Record actual RTO and RPO from the test."}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"backup-monitoring-and-maintenance",children:"Backup Monitoring and Maintenance"}),"\n",(0,t.jsx)(n.p,{children:"Monitor backup posture with AWS-native tools."}),"\n",(0,t.jsx)(n.p,{children:"Recommended checks:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"DynamoDB PITR remains enabled for required tables."}),"\n",(0,t.jsx)(n.li,{children:"S3 bucket versioning remains enabled."}),"\n",(0,t.jsx)(n.li,{children:"S3 lifecycle rules do not expire versions earlier than policy allows."}),"\n",(0,t.jsx)(n.li,{children:"OpenSearch snapshots complete successfully where configured."}),"\n",(0,t.jsx)(n.li,{children:"AWS Backup jobs complete successfully where used."}),"\n",(0,t.jsx)(n.li,{children:"Cross-region replication has no growing backlog if enabled."}),"\n",(0,t.jsx)(n.li,{children:"CloudFormation template and parameter exports are current."}),"\n",(0,t.jsx)(n.li,{children:"Restore tests are completed and documented."}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"Use AWS Config, EventBridge, CloudWatch, AWS Backup job notifications, or custom checks depending on your governance model."}),"\n",(0,t.jsx)(n.h2,{id:"compliance-and-retention",children:"Compliance and Retention"}),"\n",(0,t.jsx)(n.p,{children:"Define retention by data type."}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Data type"}),(0,t.jsx)(n.th,{children:"Retention considerations"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Document content"}),(0,t.jsx)(n.td,{children:"Business retention, legal hold, object lock, version lifecycle, purge policy."})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Document metadata"}),(0,t.jsx)(n.td,{children:"PITR window, on-demand backups, exports, audit requirements."})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Search indexes"}),(0,t.jsx)(n.td,{children:"Snapshot retention or reindex strategy."})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"User and access data"}),(0,t.jsx)(n.td,{children:"Cognito/IdP export, group membership, audit evidence."})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Logs and activity"}),(0,t.jsx)(n.td,{children:"CloudWatch retention, CloudTrail, reporting and analytics needs."})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Backup records"}),(0,t.jsx)(n.td,{children:"Evidence of backup jobs, restore tests, and recovery approvals."})]})]})]}),"\n",(0,t.jsx)(n.p,{children:"For regulated deployments, align backup retention with legal, contractual, and data residency requirements. Also confirm where backup copies, exports, and replicated data are stored."}),"\n",(0,t.jsx)(n.h2,{id:"cost-optimization",children:"Cost Optimization"}),"\n",(0,t.jsx)(n.p,{children:"Backup and recovery choices affect AWS cost."}),"\n",(0,t.jsx)(n.p,{children:"Cost drivers include:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"S3 current and noncurrent object versions"}),"\n",(0,t.jsx)(n.li,{children:"S3 replication and cross-region transfer"}),"\n",(0,t.jsx)(n.li,{children:"DynamoDB PITR, on-demand backups, and exports"}),"\n",(0,t.jsx)(n.li,{children:"AWS Backup recovery points and cross-account or cross-region copies"}),"\n",(0,t.jsx)(n.li,{children:"OpenSearch snapshots and restored domains"}),"\n",(0,t.jsx)(n.li,{children:"CloudWatch and CloudTrail retention"}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"Use lifecycle policies carefully. Lower-cost storage c
1an reduce backup cost, but it can also increase restore time or retrieval cost."}),"\n",(0,t.jsxs)(n.p,{children:["For cost planning, see ",(0,t.jsx)(n.a,{href:"/docs/platform/costs",children:"Costs & AWS Usage"}),"."]}),"\n",(0,t.jsx)(n.h2,{id:"additional-considerations",children:"Additional Considerations"}),"\n",(0,t.jsx)(n.h3,{id:"multi-tenant-environment-backups",children:"Multi-Tenant Environment Backups"}),"\n",(0,t.jsx)(n.p,{children:"For multi-site deployments, a single backup plan may still cover shared infrastructure, but recovery decisions can be tenant-specific."}),"\n",(0,t.jsx)(n.p,{children:"Plan for:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Which sites are business-critical"}),"\n",(0,t.jsx)(n.li,{children:"Whether a single site can be repaired without affecting others"}),"\n",(0,t.jsx)(n.li,{children:"How tenant-specific exports are handled"}),"\n",(0,t.jsx)(n.li,{children:"Whether tenants have different retention or residency requirements"}),"\n",(0,t.jsx)(n.li,{children:"How recovery evidence is reported per tenant"}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["For deployment model guidance, see ",(0,t.jsx)(n.a,{href:"/docs/platform/multi-tenant-vs-multi-instance",children:"Multi-Tenant and Multi-Instance Deployments"}),"."]}),"\n",(0,t.jsx)(n.h3,{id:"automation-and-integration",children:"Automation and Integration"}),"\n",(0,t.jsx)(n.p,{children:"Use automation where it reduces operational risk:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Schedule backup verification checks."}),"\n",(0,t.jsx)(n.li,{children:"Send backup and restore events to operations channels."}),"\n",(0,t.jsx)(n.li,{children:"Include recovery checks in deployment pipelines."}),"\n",(0,t.jsx)(n.li,{children:"Export stack configuration before production changes."}),"\n",(0,t.jsx)(n.li,{children:"Run document restore tests with controlled sample documents."}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"additional-resources",children:"Additional Resources"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"/docs/platform/updates_upgrades_and_rollbacks",children:"Updates, Upgrades, and Rollbacks"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"/docs/platform/document_storage",children:"Document Storage"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"/docs/features/documents",children:"Documents"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"/docs/features/search",children:"Search"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"/docs/how-tos/set-up-status-monitoring-and-alerting",children:"Status Monitoring and Alerting"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/BackupRestore.html",children:"AWS DynamoDB Backup and Restore Documentation"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://docs.aws.amazon.com/AmazonS3/latest/userguide/Versioning.html",children:"AWS S3 Versioning Documentation"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://docs.aws.amazon.com/aws-backup/latest/devguide/whatisbackup.html",children:"AWS Backup Service Documentation"})}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(l,{...e})}):l(e)}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.